Linux 互斥锁线程

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14888027/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 19:01:41  来源:igfitidea点击:

Mutex lock threads

clinuxpthreadsmutexmultiprocess

提问by resting

Am new to multi threaded/processs programming. So here's what I need to clarify.

我是多线程/进程编程的新手。所以这是我需要澄清的。

Process A code

流程A代码

pthread_mutex_lock()
    pthread_create(fooAPI(sharedResource)) //fooAPI creates another thread with shared resource that shares across processes.
pthread_mutex_unlock()

With the above pseudo code, is process B able to access sharedResourceif mutex is not unlocked?

使用上面的伪代码,sharedResource如果互斥锁没有解锁,进程B是否可以访问?

How can I access the sharedResource from process B correctly?

如何从进程 B 正确访问共享资源?

Any there any clear visual diagram that explains the relationship between mutexes, threads and processes?

是否有任何清晰的可视化图表来解释互斥锁、线程和进程之间的关系?

采纳答案by Brian

What you need to do is to call pthread_mutex_lock to secure a mutex, like this:

您需要做的是调用 pthread_mutex_lock 来保护互斥锁,如下所示:

pthread_mutex_lock(&mutex);

Once you do this, any other calls to pthread_mutex_lock(mutex)will not return until you call pthread_mutex_unlockin this thread. So if you try to call pthread_create, you will be able to create a new thread, and that thread will be able to (incorrectly) use the shared resource. You should call pthread_mutex_lockfrom within your fooAPIfunction, and that will cause the function to wait until the shared resource is available.

一旦你这样做了,pthread_mutex_lock(mutex)在你调用pthread_mutex_unlock这个线程之前,任何其他调用都不会返回。因此,如果您尝试调用 pthread_create,您将能够创建一个新线程,并且该线程将能够(错误地)使用共享资源。您应该pthread_mutex_lockfooAPI函数内部调用,这将导致函数等待共享资源可用。

So you would have something like this:

所以你会有这样的事情:

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

int sharedResource = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void* fooAPI(void* param)
{
    pthread_mutex_lock(&mutex);
    printf("Changing the shared resource now.\n");
    sharedResource = 42;
    pthread_mutex_unlock(&mutex);
    return 0;
}

int main()
{
    pthread_t thread;

    // Really not locking for any reason other than to make the point.
    pthread_mutex_lock(&mutex);
    pthread_create(&thread, NULL, fooAPI, NULL);
    sleep(1);
    pthread_mutex_unlock(&mutex);

    // Now we need to lock to use the shared resource.
    pthread_mutex_lock(&mutex);
    printf("%d\n", sharedResource);
    pthread_mutex_unlock(&mutex);
}

Edit: Using resources across processes follows this same basic approach, but you need to map the memory into your other process. Here's an example using shmem:

编辑:跨进程使用资源遵循相同的基本方法,但您需要将内存映射到其他进程。下面是一个使用 shmem 的例子:

#include <stdio.h>
#include <unistd.h>
#include <sys/file.h>
#include <sys/mman.h>
#include <sys/wait.h>

struct shared {
    pthread_mutex_t mutex;
    int sharedResource;
};

int main()
{
    int fd = shm_open("/foo", O_CREAT | O_TRUNC | O_RDWR, 0600);
    ftruncate(fd, sizeof(struct shared));

    struct shared *p = (struct shared*)mmap(0, sizeof(struct shared),
        PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

    p->sharedResource = 0;

    // Make sure it can be shared across processes
    pthread_mutexattr_t shared;
    pthread_mutexattr_init(&shared);
    pthread_mutexattr_setpshared(&shared, PTHREAD_PROCESS_SHARED);

    pthread_mutex_init(&(p->mutex), &shared);

    int i;
    for (i = 0; i < 100; i++) {
        pthread_mutex_lock(&(p->mutex));
        printf("%d\n", p->sharedResource);
        pthread_mutex_unlock(&(p->mutex));
        sleep(1);
    }

    munmap(p, sizeof(struct shared*));
    shm_unlink("/foo");
}

Writing the program to make changes to p->sharedResource is left as an exercise for the reader. :-)

编写程序以更改 p->sharedResource 留给读者作为练习。:-)

Forgot to note, by the way, that the mutex has to have the PTHREAD_PROCESS_SHARED attribute set, so that pthreads will work across processes.

顺便说一句,忘了注意互斥锁必须设置 PTHREAD_PROCESS_SHARED 属性,以便 pthread 可以跨进程工作。

回答by c.fogelklou

Q1.) Assuming process B tries to take ownership of the same mutex you locked in process A (you left that out of your pseudocode) then no, process B cannot access sharedResource while the mutex is locked since it will sit waiting to lock the mutex until it is released by process A. It will return from the mutex_lock() function when the mutex is locked (or when an error occurs!)

Q1.) 假设进程 B 试图获得你在进程 A 中锁定的同一个互斥锁的所有权(你把它从你的伪代码中去掉了)那么不,当互斥锁被锁定时,进程 B 不能访问共享资源,因为它会等待锁定互斥锁直到它被进程 A 释放。当互斥锁被锁定时(或发生错误时!),它将从 mutex_lock() 函数返回

Q2.) In Process B, ensure you always lock the mutex, access the shared resource, and then unlock the mutex. Also, check the return code from the mutex_lock( pMutex ) routine to ensure that you actually own the mutex, and ONLY unlock the mutex if you have locked it. Do the same from process A.

Q2.) 在进程 B 中,确保始终锁定互斥锁,访问共享资源,然后解锁互斥锁。此外,检查 mutex_lock( pMutex ) 例程的返回代码以确保您确实拥有互斥锁,并且只有在您锁定互斥锁时才解锁它。从进程A做同样的事情。

Both processes should basically do the same thing when accessing the mutex.
lock() If the lock succeeds, then { access sharedResource unlock() }

两个进程在访问互斥锁时基本上应该做同样的事情。
lock() 如果锁定成功,则 { access sharedResource unlock() }

Q3.) Yes, there are lots of diagrams: =) https://www.google.se/search?q=mutex+thread+process&rlz=1C1AFAB_enSE487SE487&um=1&ie=UTF-8&hl=en&tbm=isch&source=og&sa=N&tab=wi&ei=ErodUcSmKqf54QS6nYDoAw&biw=1200&bih=1730&sei=FbodUbPbB6mF4ATarIBQ

Q3.) 是的,有很多图:=) https://www.google.se/search?q=mutex+thread+process&rlz=1C1AFAB_enSE487SE487&um=1&ie=UTF-8&hl=en&tbm=isch&source=og&sa=N&tab=wi&ei =ErodUcSmKqf54QS6nYDoAw&biw=1200&bih=1730&sei=FbodUbPbB6mF4ATarIBQ

回答by Aditya Sihag

A process consists of at least one thread (think of the main function). Multi threaded code will just spawn more threads. Mutexes are used to create locks around shared resources to avoid data corruption / unexpected / unwanted behaviour. Basically it provides for sequential execution in an asynchronous setup - the requirement for which stems from non-const non-atomic operations on shared data structures.

一个进程至少由一个线程组成(想想 main 函数)。多线程代码只会产生更多线程。互斥体用于在共享资源周围创建锁,以避免数据损坏/意外/不需要的行为。基本上,它提供了异步设置中的顺序执行 - 其要求源于对共享数据结构的非常量非原子操作。

A vivid description of what mutexes would be the case of people (threads) queueing up to visit the restroom (shared resource). While one person (thread) is using the bathroom easing him/herself (non-const non-atomic operation), he/she should ensure the door is locked (mutex), otherwise it could lead to being caught in full monty (unwanted behaviour)

对人们(线程)排队上厕所(共享资源)的情况的互斥的生动描述。当一个人(线程)正在使用浴室放松自己(非常量非原子操作)时,他/她应该确保门是锁定的(互斥锁),否则可能会导致陷入困境(不良行为) )

回答by parasrish

Below, code snippet, will help you in understanding the mutex-lock-unlock concept. Attempt dry-run on the code. (further by varying the wait-time and process-time, you can build you understanding).

下面的代码片段将帮助您理解互斥锁解锁的概念。尝试对代码进行试运行。(进一步通过改变等待时间和处理时间,你可以建立你的理解)。

Code for your reference:

代码供您参考:

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

void in_progress_feedback(int);

int global = 0;
pthread_mutex_t mutex;
void *compute(void *arg) {

    pthread_t ptid = pthread_self();
    printf("ptid : %08x \n", (int)ptid);    

    int i;
    int lock_ret = 1;   
    do{

        lock_ret = pthread_mutex_trylock(&mutex);
        if(lock_ret){
            printf("lock failed(%08x :: %d)..attempt again after 2secs..\n", (int)ptid,  lock_ret);
            sleep(2);  //wait time here..
        }else{  //ret =0 is successful lock
            printf("lock success(%08x :: %d)..\n", (int)ptid, lock_ret);
            break;
        }

    } while(lock_ret);

        for (i = 0; i < 10*10 ; i++) 
        global++;

    //do some stuff here
    in_progress_feedback(10);  //processing-time here..

    lock_ret = pthread_mutex_unlock(&mutex);
    printf("unlocked(%08x :: %d)..!\n", (int)ptid, lock_ret);

     return NULL;
}

void in_progress_feedback(int prog_delay){

    int i=0;
    for(;i<prog_delay;i++){
    printf(". ");
    sleep(1);
    fflush(stdout);
    }

    printf("\n");
    fflush(stdout);
}

int main(void)
{
    pthread_t tid0,tid1;
    pthread_mutex_init(&mutex, NULL);
    pthread_create(&tid0, NULL, compute, NULL);
    pthread_create(&tid1, NULL, compute, NULL);
    pthread_join(tid0, NULL);
    pthread_join(tid1, NULL);
    printf("global = %d\n", global);
    pthread_mutex_destroy(&mutex);
          return 0;
}