2
votes

I wanna ask you some basic thing but it really bothers me a lot. I'm currently studying 'pthread mutex' for system programming and as far as I know, when 'pthread_mutex_lock' is called only current thread is executed not any others. Can I think like this?

And when it comes to 'pthread_mutex_unlock', when this function is called, does the current thread pass the lock permission to others and wait until some other thread calls unlock function again? Or does every thread including current thread execute simultaneously until one of them calls lock function?

Here's the code I was studying:

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

    enum { STATE_A, STATE_B } state = STATE_A;
    pthread_cond_t condA = PTHREAD_COND_INITIALIZER;
    pthread_cond_t condB = PTHREAD_COND_INITIALIZER;
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

    void *threadA()
    {
        printf("A start\n");
        int i = 0, rValue, loopNum;

        while(i<3)
        {

            pthread_mutex_lock(&mutex);
            while(state != STATE_A)
            {
                printf("a\n");
                pthread_cond_wait(&condA, &mutex);
            }

            pthread_mutex_unlock(&mutex);    
            pthread_cond_signal(&condB);


        for(loopNum = 1; loopNum <= 5; loopNum++)
        {
            printf("Hello %d\n", loopNum);
        }

        pthread_mutex_lock(&mutex);
        state = STATE_B;
        printf("STATE_B\n");
        pthread_cond_signal(&condB);
        pthread_mutex_unlock(&mutex);

        i++;
    }

    return 0;
}

void *threadB()
{
    printf("B start\n");
    int n = 0, rValue;

    while(n<3)
    {
        pthread_mutex_lock(&mutex);
        while (state != STATE_B)
        {
            printf("b\n");
            pthread_cond_wait(&condB, &mutex);
        }

        pthread_mutex_unlock(&mutex);    
        printf("Goodbye\n");
        pthread_mutex_lock(&mutex);
        state = STATE_A;
        printf("STATE_A\n");
        pthread_cond_signal(&condA);
        pthread_mutex_unlock(&mutex);
        n++;
    }

    return 0;
}

int main(int argc, char *argv[])
{
    pthread_t a, b;

    pthread_create(&a, NULL, threadA, NULL);
    pthread_create(&b, NULL, threadB, NULL);

    pthread_join(a, NULL);
    pthread_join(b, NULL);
}

I kind of modified some of the original parts to make sure what's going on in this code such as adding printf("A start\n"), printf("a\n") so on.

And here are some outputs:

Output 1

B start
b
A start
Hello 1
Hello 2
Hello 3
Hello 4
Hello 5
b
STATE_B
a
Goodbye
STATE_A
b
Hello 1
Hello 2
Hello 3
Hello 4
Hello 5
b
STATE_B
a
Goodbye
STATE_A
b
Hello 1
Hello 2
Hello 3
Hello 4
Hello 5
b
STATE_B
Goodbye
STATE_A

Output 2

B start
b
A start
Hello 1
Hello 2
Hello 3
Hello 4
Hello 5
STATE_B
a
Goodbye
STATE_A
b
Hello 1
Hello 2
Hello 3
Hello 4
Hello 5
STATE_B
a
Goodbye
STATE_A
b
Hello 1
Hello 2
Hello 3
Hello 4
Hello 5
STATE_B
Goodbye
STATE_A

So I learned that when threads are called, they are called simultaneously. Based on this logic, I added the 'printf("A start\n")' and 'printf("B start\n")' in the beginning of the each thread function 'threadA() and threadB()'. But always 'printf("B start\n")' comes up first. If they are called at the same time, don't they have to come up alternatively, at least randomly?

Also after the first 'Hello' loop, I'm assuming 'Goodbye' message always should be earlier than 'a' since I guess the 'pthread_mutex_unlock' in ThreadA calls ThreadB and waits until ThreadB calls unlock function. I want to know how this code works.

I'm guessing I would be totally wrong and misunderstood a lot of parts since I'm a newbie in this field. But wanna get the answer. Thank you for reading this :)

2
Your question is too unfocused. Please just ask one specific question at a time and get straight to the point. pthread_mutex_lock will suspend the calling thread if the lock is already held. When another thread calls pthread_mutex_unlock the kernel will select a currently pthread_mutex_locked blocked thread (if any) and unblock it (schedule it for execution).kaylum

2 Answers

2
votes

when 'pthread_mutex_lock' is called only current thread is executed not any others. Can I think like this?

I guess you can think like that, but you'll be thinking incorrectly. pthread_mutex_lock() doesn't cause only the calling thread to execute. Rather, it does one of two things:

  1. If the mutex wasn't already locked, it locks the mutex and returns immediately.
  2. If the mutex was already locked, it puts the calling thread to sleep, to wait until the mutex has become unlocked. Only after pthread_mutex_lock() has successfully acquired the lock, will pthread_mutex_lock() return.

Note that in both cases, the promise that pthread_mutex_lock() makes to the calling thread is this: when pthread_mutex_lock() returns zero/success, the mutex will be locked and the calling thread will be the owner of the lock. (The other possibility is that phread_mutex_lock() will return a negative value indicating an error condition, but that's uncommon in practice so I won't dwell on it)

when it comes to 'pthread_mutex_unlock', does the current thread pass the lock permission to others and wait until some other thread calls unlock function again?

The first thing to clarify is that pthread_mutex_unlock() never waits for anything; unlike pthread_mutex_lock(), pthread_mutex_unlock() always returns immediately.

So what does pthread_mutex_unlock() do?

  1. Unlocks the mutex (note that the mutex must have already been locked by a previous call to pthread_mutex_lock() in the same thread. If you call pthread_mutex_unlock() on a mutex without having previously called pthread_mutex_lock() to acquire that same mutex, then your program is buggy and won't work correctly)
  2. Notifies the OS's thread-scheduler (through some mechanism that is deliberately left undocumented, since as a user of the pthreads library you don't need to know or care how it is implemented) that the mutex is now unlocked. Upon receiving that notification, the OS will check to see what other threads (if any) are blocked inside their own call to pthread_mutex_lock(), waiting to acquire this mutex, and if there are any, it will wake up one of those threads so that that thread may acquire the lock and its pthread_mutex_lock() call can then return. All that may happen before or after your thread's call to pthread_mutex_unlock() returns; the exact order of execution is indeterminate and doesn't really matter.

I guess the 'pthread_mutex_unlock' in ThreadA calls ThreadB and waits until ThreadB calls unlock function.

pthread_mutex_unlock() does no such thing. In general, threads don't/can't call functions in other threads. For what pthread_mutex_unlock() does do, see my description above.

0
votes

pthread_mutex_lock() doesn't mean only one thread will execute - it just means that any other thread that also tries to call pthread_mutex_lock() on the same mutex object will be suspended until the first thread releases the lock with pthread_mutex_unlock().

If the other threads aren't trying to lock the same mutex, they can continue running simultaneously.

If multiple threads have tried to lock the same mutex while it is locked by the first thread, then when the mutex is released by the first thread with pthread_mutex_unlock() only one of them will be able to proceed (and then when that thread itself calls pthread_mutex_unlock(), another waiting thread will be able to proceed and so on).

Note that a thread waiting for a mutex to be unlocked will not necessarily start executing immediately upon the mutex being unlocked.