pthread mutex 解锁是如何工作的?线程会同时出现吗?

How does pthread mutex unlock work? And do threads come up at the same time?

我想问你一些基本的事情,但它真的让我很困扰。 我目前正在研究 'pthread mutex' 系统编程,据我所知,当 'pthread_mutex_lock' 被调用时,只执行当前线程而不执行任何其他线程。我可以这样想吗?

还有'pthread_mutex_unlock',这个函数调用的时候,是不是当前线程把lock权限传给其他线程,等待其他线程再次调用unlock函数?还是包括当前线程在内的每个线程都同时执行,直到其中一个线程调用锁定函数?

这是我正在研究的代码:

    #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);
}

我修改了一些原始部分以确保此代码中发生了什么,例如添加 printf("A start\n")、printf("a\n") 等等。

这里有一些输出:

输出 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

输出 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

于是我了解到调用线程的时候是同时调用的。基于这个逻辑,我在每个线程函数'threadA() and threadB()'的开头添加了'printf("A start\n")'和'printf("B start\n")'。但总是 'printf("B start\n")' 先出现。如果他们同时被调用,他们是否必须交替出现,至少是随机出现?

同样在第一个 'Hello' 循环之后,我假设 'Goodbye' 消息总是应该早于 'a' 因为我猜 ThreadA 中的 'pthread_mutex_unlock' 调用 ThreadB 并且等到 ThreadB 调用解锁函数。我想知道这段代码是如何工作的。

我猜我是完全错误的并且误解了很多部分,因为我是这个领域的新手。但想得到答案。感谢您阅读本文:)

pthread_mutex_lock() 并不意味着只有一个线程将执行 - 它只是意味着 尝试调用 pthread_mutex_lock() [=23] 的任何其他线程=]在同一个互斥对象上将被挂起,直到第一个线程用pthread_mutex_unlock()释放锁。

如果其他线程没有尝试锁定同一个互斥锁,它们可以同时继续 运行。

如果多个线程在第一个线程锁定同一个互斥量时尝试锁定同一个互斥量,那么当第一个线程使用 pthread_mutex_unlock() 释放互斥量时,只有其中一个能够继续(然后当该线程本身调用 pthread_mutex_unlock() 时,另一个等待线程将能够继续进行等等)。

请注意,等待解锁互斥锁的线程不一定会在解锁互斥锁后立即开始执行。

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

我想你可以这样想,但你会想错了。 pthread_mutex_lock() 不会只导致调用线程执行。相反,它执行以下两项操作之一:

  1. 如果互斥量尚未锁定,它会立即锁定互斥量和 returns。
  2. 如果互斥锁已经被锁定,它会让调用线程进入睡眠状态,等待互斥锁解锁。只有在 pthread_mutex_lock() 成功获取锁后, pthread_mutex_lock() 才会 return.

请注意,在这两种情况下,pthread_mutex_lock() 对调用线程的承诺是这样的:当 pthread_mutex_lock() returns zero/success 时, mutex 将被锁定,调用线程将成为锁的所有者。 (另一种可能性是 phread_mutex_lock() 将 return 表示错误情况的负值,但这在实践中并不常见,所以我不会详述它)

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?

首先要澄清的是 pthread_mutex_unlock() 从不等待任何事情;不像 pthread_mutex_lock(),pthread_mutex_unlock() 总是 return 立即。

那么 pthread_mutex_unlock() 是做什么的?

  1. 解锁互斥体(请注意,互斥体必须已被同一线程中先前对 pthread_mutex_lock() 的调用锁定。如果您在互斥体上调用 pthread_mutex_unlock() 而没有之前调用 pthread_mutex_lock() 来获取相同的互斥锁,那么你的程序有问题,无法正常工作)
  2. 通知 OS 的线程调度程序(通过一些故意未记录的机制,因为作为 pthreads 库的用户,您不需要知道或关心它是如何实现的)互斥量现已解锁。收到该通知后,OS 将检查在它们自己对 pthread_mutex_lock() 的调用中阻塞了哪些其他线程(如果有的话),等待获取此互斥锁,如果有的话,它将唤醒其中一个线程,以便该线程可以获取锁,然后它的 pthread_mutex_lock() 调用可以 return。在您的线程调用 pthread_mutex_unlock() returns 之前或之后可能发生的所有事情;确切的执行顺序是不确定的,并不重要。

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

pthread_mutex_unlock() 不会做这样的事情。一般来说,线程不会t/can调用其他线程中的函数。对于 pthread_mutex_unlock() 做什么,请参阅我上面的描述。