为什么 cond 变量不是原子释放的?

Why is the cond variable not atomicaly releasing?

以下代码可以在《Pthreads编程》一书中找到(O'Reilly媒体):

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

#define TCOUNT 10
#define WATCH_COUNT 12

int count = 0;
pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t count_threshold_cv = PTHREAD_COND_INITIALIZER;
int thread_ids[3] = {0,1,2};

void watch_count(int *idp);
void inc_count(int *idp);

extern int
main(void)
{
    pthread_t threads[3];
    pthread_create(&threads[0], NULL, inc_count,   &thread_ids[0]);
    pthread_create(&threads[1], NULL, inc_count,   &thread_ids[1]);
    pthread_create(&threads[2], NULL, watch_count, &thread_ids[2]);

    for(int i=0; i<3; i++)
        pthread_join(threads[i],NULL);

    return 0;
}

void watch_count(int *idp)
{
    pthread_mutex_lock(&count_mutex);
    printf("Waiting condition\n");
    while(count <= WATCH_COUNT)
    {
        pthread_cond_wait(&count_threshold_cv,&count_mutex);
        printf("watch_count(): Thread %d, Count is %d\n", *idp, count);
    }
    pthread_mutex_unlock(&count_mutex);
}

void inc_count(int *idp)
{
    for(int i=0; i<TCOUNT; i++)
    {
        pthread_mutex_lock(&count_mutex);
        count++;
        printf("inc_counter(): Thread %d, old count %d, new count %d\n", *idp, count-1, count);
        if(count == WATCH_COUNT)
        {
            printf("release\n");
            pthread_cond_signal(&count_threshold_cv);
        }    

        pthread_mutex_unlock(&count_mutex);
    }
}

预期的行为是创建 2 个线程,将同一个全局变量“计数”增加到 20,当它达到 12 时,它应该释放条件并重新进入 watch_counter 线程,但是由于某种原因,它不会立即进行。

输出如下

inc_counter(): Thread 0, old count 0, new count 1
inc_counter(): Thread 1, old count 1, new count 2
Waiting condition
inc_counter(): Thread 0, old count 2, new count 3
inc_counter(): Thread 1, old count 3, new count 4
inc_counter(): Thread 0, old count 4, new count 5
inc_counter(): Thread 1, old count 5, new count 6
inc_counter(): Thread 0, old count 6, new count 7
inc_counter(): Thread 1, old count 7, new count 8
inc_counter(): Thread 0, old count 8, new count 9
inc_counter(): Thread 1, old count 9, new count 10
inc_counter(): Thread 0, old count 10, new count 11
inc_counter(): Thread 1, old count 11, new count 12
releasing
inc_counter(): Thread 0, old count 12, new count 13
inc_counter(): Thread 1, old count 13, new count 14
watch_count(): Thread 2, Count is 14
inc_counter(): Thread 0, old count 14, new count 15
inc_counter(): Thread 1, old count 15, new count 16
inc_counter(): Thread 0, old count 16, new count 17
inc_counter(): Thread 1, old count 17, new count 18
inc_counter(): Thread 0, old count 18, new count 19
inc_counter(): Thread 1, old count 19, new count 20

有谁知道为什么会这样?

线程可以按任何顺序执行,除非您强制执行某些特定顺序。

你强制的唯一命令是当count小于或等于WATCH_COUNTwatch_count不能向前推进。这显然不会发生。

如果您需要强制执行任何其他顺序,则需要编写代码来执行此操作。否则,线程可以按任何顺序执行。一个好的实现不会比必须的更频繁地切换线程,并且您可能有一个好的实现。

您对它会“立即”执行的期望似乎没有任何依据。其他线程已经运行了,不等了,为什么不继续往前推进呢?两个 inc_count 线程已经 运行 并且它们从不等待任何东西。

pthread_cond_signal函数使当前正在等待条件变量的一个线程停止等待条件变量。它在获取互斥量之前仍然无法取得进展,因为它需要互斥量来检查是否可以退出 while 条件。还有另外两个线程争用该互斥锁,但不能保证它会获胜。