Mutex lock threads

resting picture resting · Feb 15, 2013 · Viewed 100.6k times · Source

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

Process A code

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 sharedResource if mutex is not unlocked?

How can I access the sharedResource from process B correctly?

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

Answer

Brian picture Brian · Feb 15, 2013

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

pthread_mutex_lock(&mutex);

Once you do this, any other calls to pthread_mutex_lock(mutex) will not return until you call pthread_mutex_unlock in 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_lock from within your fooAPI function, and that will cause the function to wait until the shared resource is available.

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:

#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. :-)

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.