简体   繁体   English

如何在本地使用互斥变量锁定线程?

[英]How to lock thread by using mutex variable locally?

When i programming mutex in pthread i used to make mutex lock variable ( pthread_mutex_t mutex ) globally.当我在 pthread 中编程互斥锁时,我曾经全局创建互斥锁锁变量( pthread_mutex_t mutex )。 When i see many example program most of the cases mutex variable placed globally.当我看到许多示例程序时,大多数情况下互斥变量都放置在全局范围内。

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *add1_fun(void* arg);
void *add2_fun(void* arg);
pthread_mutex_t mutex;

void *add1_fun(void* arg) 
{
    int t_num = (int)arg;
    int i = 0;

    pthread_mutex_lock(&mutex);

    printf("Thread %d created and running \n", t_num); /*critical section start*/
    sleep(3);
    printf("Thread %d finishes the work\n", t_num); /*critical section end*/
    pthread_mutex_unlock (&mutex);

    pthread_exit(NULL);
}

int main(int argc, char *argv[])
{
    pthread_t mythread1;
    pthread_t mythread2;
    pthread_attr_t myattr;
    void *joinResult;
    int x = 0;
    int t_arg = 1;
    pthread_mutex_init(&mutex, NULL);
    pthread_attr_init(&myattr);
    pthread_attr_setdetachstate(&myattr, PTHREAD_CREATE_JOINABLE);                 

    if((pthread_create(&mythread1, &myattr, add1_fun,  (void*)t_arg) != 0)){
        printf("Error, thread not created properly\n");
        return 1;
    }
    t_arg = 2;
    if((pthread_create(&mythread2, &myattr, add1_fun,  (void*)t_arg) != 0)){
        printf("Error, thread not created properly\n");
        return 1;
    }
    pthread_attr_destroy(&myattr);
    if(pthread_join(mythread1, &joinResult) != 0 ){
        printf("Error pthread join \n");
        return 1;
    }
    printf("Main : Thread1 joined with result of %d\n", (int)joinResult);
    if(pthread_join(mythread2, &joinResult) != 0 ){
        printf("Error pthread join \n");
        return 1;
    }
    printf("Main : Thread2 joined with result of %d\n", (int)joinResult);
    printf("main finishes the work\n");

    pthread_exit(NULL);
}

What is my doubt is, In this situation everywhere in the program can take mutex variable and do lock and unlock the mutex.我的疑问是,在这种情况下,程序中的任何地方都可以使用互斥变量并锁定和解锁互斥锁。 This will reduce security.这会降低安全性。

Is it possible to make lock in the thread by making mutex variable locally in thread handler.是否可以通过在线程处理程序中本地创建互斥锁变量来锁定线程。 like below program structure像下面的程序结构

void *add1_fun(void* arg)
{
    pthread_mutex_t mutex;
    pthread_mutex_lock(&mutex);

/* critical section */

    pthread_mutex_unlock (&mutex);
}
int main()
{
   /* code */
}

I think this question may take no sense, please help me out, I am not good at multi threading.我认为这个问题可能没有意义,请帮帮我,我不擅长多线程。

I am using gcc under linux.我在 linux 下使用 gcc。

Thanks.谢谢。

A local variable is local to just the specific function invocation. 局部变量仅对于特定的函数调用是局部的。 If you want a "local" variable to be static between function invocations then you have to make the variable static . 如果您希望函数调用之间的“局部”变量是静态的,则必须使该变量成为static

The idea of mutex, is that everyone can try to lock it, but, at any time only one will succeed. 互斥锁的想法是,每个人都可以尝试锁定它,但是在任何时候,只有一个能够成功。

If you use local mutex, you can lock it. 如果使用本地互斥锁,则可以将其锁定。 but other threads, will create their own local mutex, and will also succeed to lock it. 但是其他线程将创建自己的本地互斥体,并将成功锁定它。 not really the point, is it... 不是重点,是...

If you dont want to use the mutex globaly, you can declare it as atatic, and then, everyone will use the same mutex. 如果您不想全局使用互斥锁,则可以将其声明为atatic,然后每个人都将使用相同的互斥锁。

What is a mutex ? 什么是互斥锁

It is an object used for accesing programs resources by more than one threads, but only one thread at any time has access to the resource. 它是一个对象,用于通过多个线程访问程序资源,但是在任何时候只有一个线程可以访问该资源。 I don't think that you have to think for security issuses from the mutex perspective, because once locked, only the thread that locked it can unlock it. 我认为您不必从互斥锁的角度考虑安全问题,因为一旦锁定,只有锁定它的线程才能解锁它。

So you either make the mutex global, or static, but never local. 因此,您可以将互斥锁设置为全局或静态,而不是局部。

The problem is that if you declared a mutex as a local variable to a function, such as: 问题是,如果您声明互斥锁作为函数的局部变量,例如:

void foo() {
    pthread_mutex_t mutex;
    /* ... */
}

It wouldn't work because every time someone calls foo(), it "creates" a brand new mutex and it can't be used to synchronise to invocation to foo() because the two caller will not lock the same mutex. 这是行不通的,因为每次有人调用foo()时,它都会“创建”一个全新的互斥锁,并且由于两个调用者不会锁定同一互斥锁,因此它不能用于与foo()的调用同步。

The only solution, if you don't want to place the "mutex" variable in some global file or similar, is to declared is as static 如果不想将“ mutex”变量放置在某些全局文件或类似文件中,则唯一的解决方案是声明为静态

void foo() {
    static pthread_mutex_t mutex;
    /* ... */
}

However, please bear in mind that this is anyway a global mutex! 但是,请记住,这无论如何都是全局互斥! This means that you can anyway pass the &mutex to some other function like: 这意味着您仍然可以将&mutex传递给其他函数,例如:

void corrupt_it(pthread_mutex_t *p_mutex);
void foo() {
    static pthread_mutex_t mutex;
    corrupt_it(&mutex);
}

A local mutex locks the section of code in one thread. 本地互斥锁将代码段锁定在一个线程中。 The other thread also will lock it. 另一个线程也将其锁定。 And the next one too. 还有下一个。 But none of them knows about the other locks. 但是他们都不知道其他锁。 So You will achieve mostly no thread-safety if you use the local approach. 因此,如果使用本地方法,几乎​​不会实现线程安全。

If you put it locally its scope will be local. 如果将其放在本地,则其范围将是本地的。 Every instance of the function will have its own little local mutex that has no connection to the others. 该函数的每个实例都将具有自己的局部互斥体,该互斥体与其他实例没有任何关系。

You can keep each thread's worker function argument independent, and with a pointer pointing to the same "manager" variable, which hold the mutex .您可以保持每个线程的工作人员 function 参数独立,并使用指向相同“管理器”变量的指针,该变量包含mutex

As a reference code example, using 4 threads to save money to a same bank account, I create two structs thread_manager_t and thread_data_t , thus there is no global variables.作为参考代码示例,使用 4 个线程为同一个银行帐户存钱,我创建了两个结构thread_manager_tthread_data_t ,因此没有全局变量。

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>

// all thread's thread_data_t variable will pointing to the same thread_manager_t variable
struct thread_manager_t
{
    int total_money;
    pthread_mutex_t mutex;
};

// each thread will have an independent thread_data_t variable
struct thread_data_t
{
    thread_manager_t* manager;
};

void* save_money_to_bank(void* param)
{
    thread_data_t* thread_data = (thread_data_t*)param;
    for (int i = 0; i < 10000; i++)
    {
        pthread_mutex_lock(&thread_data->manager->mutex);
        thread_data->manager->total_money++;
        pthread_mutex_unlock(&thread_data->manager->mutex);
    }
    return NULL;
}

int main()
{
    const int thread_num = 4;
    pthread_t t[thread_num];

    thread_data_t* thread_data = (thread_data_t*)malloc(sizeof(thread_data_t) * thread_num);
    thread_manager_t thread_manager;
    pthread_mutex_init(&thread_manager.mutex, NULL);
    for (int i = 0; i < thread_num; i++)
    {
        thread_data[i].manager = &thread_manager;
        pthread_create(&t[i], NULL, save_money_to_bank, &thread_data[i]);
    }

    for (int i = 0; i < thread_num; i++)
    {
        pthread_join(t[i], NULL);
    }

    printf("finally, total_money = %d\n", thread_manager.total_money);

    free(thread_data);
    pthread_mutex_destroy(&thread_manager.mutex);

    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM