pthread互斥锁如何解锁?并且线程同时出现吗?

时间:2016-11-29 18:46:28

标签: linux multithreading pthreads mutex

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

当谈到'pthread_mutex_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()和threadB()'的开头添加了'printf(“A start \ n”)'和'printf(“B start \ n”)'。但总是'printf(“B start \ n”)'首先出现。如果同时调用它们,它们是否必须交替出现,至少随机出现?

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

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

2 个答案:

答案 0 :(得分:2)

  

当调用'pthread_mutex_lock'时,只执行当前线程   没有其他人。我能这样想吗?

我想你可以这么想,但你会错误地思考。 pthread_mutex_lock()不会仅导致调用线程执行。相反,它做了两件事之一:

  1. 如果互斥锁尚未锁定,则会锁定互斥锁并立即返回。
  2. 如果互斥锁已被锁定,则会将调用线程置于休眠状态,等待互斥锁解锁。只有在pthread_mutex_lock()成功获取锁定后,才会返回pthread_mutex_lock()。
  3. 请注意,在这两种情况下,pthread_mutex_lock()对调用线程的承诺是这样的:当pthread_mutex_lock()返回零/成功时,互斥锁将被锁定,调用线程将成为锁的所有者。 (另一种可能性是phread_mutex_lock()将返回一个表示错误情况的负值,但这在实践中并不常见,所以我不会详述它)

      

    当涉及'pthread_mutex_unlock'时,当前线程是否通过   对其他人的锁定权限,并等待其他线程调用   再次解锁功能?

    要澄清的第一件事是pthread_mutex_unlock()永远不会等待任何事情;与pthread_mutex_lock()不同,pthread_mutex_unlock()始终会立即返回。

    那么pthread_mutex_unlock()会做什么?

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

      我猜ThreadA中的'pthread_mutex_unlock'调用ThreadB并等待   直到ThreadB调用解锁函数。

      pthread_mutex_unlock()没有这样的事情。通常,线程不会/不能在其他线程中调用函数。对于pthread_mutex_unlock()的操作,请参阅上面的描述。

答案 1 :(得分:0)

pthread_mutex_lock()并不意味着只有一个线程会执行 - 它只是意味着试图在同一个互斥对象上调用pthread_mutex_lock() 的任何其他线程将暂停,直到第一个帖子使用pthread_mutex_unlock()释放锁定。

如果其他线程没有尝试锁定相同的互斥锁,则可以继续同时运行。

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

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