Concurrency pthread和条件变量

Concurrency pthread和条件变量,concurrency,pthreads,condition-variable,Concurrency,Pthreads,Condition Variable,我正在跟随来自的关于pthread的教程 #包括 #包括 #包括 pthread\u mutex\u t count\u mutex=pthread\u mutex\u初始值设定项; pthread\u mutex\u t condition\u mutex=pthread\u mutex\u初始值设定项; pthread_cond_t condition_cond=pthread_cond_初始值设定项; void*functionCount1(); void*functionCount2()

我正在跟随来自的关于pthread的教程

#包括
#包括
#包括
pthread\u mutex\u t count\u mutex=pthread\u mutex\u初始值设定项;
pthread\u mutex\u t condition\u mutex=pthread\u mutex\u初始值设定项;
pthread_cond_t condition_cond=pthread_cond_初始值设定项;
void*functionCount1();
void*functionCount2();
整数计数=0;
#定义完成的计数为10
#定义计数\u HALT1 3
#定义计数\u HALT2 6
main()
{
pthread_t thread1,thread2;
pthread_create(&thread1,NULL,&functionCount1,NULL);
pthread_create(&thread2,NULL,&functionCount2,NULL);
pthread_join(thread1,NULL);
pthread_join(thread2,NULL);
出口(0);
}
void*functionCount1()
{
对于(;;)
{
pthread_mutex_lock(&condition_mutex);
而(count>=count\u HALT1&&count=count\u DONE)返回(NULL);
}
}
void*functionCount2()
{
对于(;;)
{
pthread_mutex_lock(&condition_mutex);
如果(计数<计数|停止1 |计数>计数|停止2)
{
pthread_cond_信号(&condition_cond);
}
pthread_mutex_unlock(&condition_mutex);
pthread_mutex_lock(&count_mutex);
计数++;
printf(“计数器值函数count2:%d\n”,count);
pthread_mutex_unlock(&count_mutex);
如果(计数>=计数完成)返回(空);
}
}
作者补充说,对于介于
COUNT\u HALT1
COUNT\u HALT2
之间的值,
functioncount1()

示例输出如下所示:

Counter value functionCount1: 1
Counter value functionCount1: 2
Counter value functionCount1: 3
Counter value functionCount2: 4
Counter value functionCount2: 5
Counter value functionCount2: 6
Counter value functionCount2: 7
Counter value functionCount1: 8
Counter value functionCount1: 9
Counter value functionCount1: 10
Counter value functionCount2: 11
根据我对代码的观察,3不应该由
functionCount2
计算吗?在
functionCount1
中的while循环中,它对任何值调用
wait()
,包括3,这使我认为3应该由
functionCount2
计算,而不是
functionCount1


为什么不是这样

一个线程可以读取
count
,而只保留
条件的互斥(其中
count
根据
count\u HALT1
count\u HALT
进行测试)或根本不保留互斥(其中
count
根据
count\u DONE
进行测试)而另一个线程可以修改
count
,只保留
count\u互斥锁。这种不同步的访问会导致未定义的行为,正如@EOF在对问题的评论中所指出的,因此代码根本不正确

也就是说,即使我们只运行
functionCount1()
,而不运行其他线程(这样就不会发生不同步的访问),我们仍然希望看到以下输出:

Counter value functionCount1: 1
Counter value functionCount1: 2
Counter value functionCount1: 3
这是因为计数器值是在增量之后打印的,所以在上一次迭代中,它看到一个初始计数器值2,不等待,增加计数器,然后打印新的计数器值3

请注意,在原始代码中,即使忽略非同步访问,
functionCount1
仍有可能执行从3到4的增量。这是因为在
functionCount1
看到
count
值为2并决定不等待时,实际上锁定了
count\u互斥锁
,该值可能会被另一个线程增加

要删除对
count
的非同步访问并修复上一段中提到的争用,只需完全删除
条件\u mutex
并使用
count\u mutex
,将其锁定在
pthread\u cond\u wait()
返回和
计数的实际增量之间。这是一般模式:调用
pthread\u cond\u wait()
时锁定的互斥体应该是保护共享状态的互斥体,您正在使用条件变量等待该共享状态(这里,该共享状态只是
count
变量):


如上所述,您可能再也看不到按严格计数顺序排列的
printf()
输出,因为我们不再强制printf()以原子方式递增。

对于非同步、非只读、,从多个线程对对象进行非原子访问。@EOF但有互斥锁以确保我们正在同步3到6之间的值。作者甚至提到,“唯一可以确保的是函数count2将增加值count\u HALT1和count\u HALT2之间的计数。其他一切都是随机的。”C11标准草案n1570:5.1.2.4多线程执行和数据争用4如果其中一个修改内存位置,而另一个读取或修改同一内存位置,则两个表达式求值会发生冲突。25如果一个程序在不同的线程中包含两个冲突的操作,则该程序的执行包含数据竞争,其中至少一个操作不是原子的,并且两个操作都不在另一个线程之前发生。任何这样的数据竞争都会导致未定义的行为。未定义。行为。
void *functionCount1()
{
    for(;;)
    {
        pthread_mutex_lock( &count_mutex );
        while( count >= COUNT_HALT1 && count <= COUNT_HALT2 )
        {   
            pthread_cond_wait( &condition_cond, &count_mutex );
        }

        count++;
        printf("Counter value functionCount1: %d\n",count);

        if (count >= COUNT_DONE)
        {   
            pthread_mutex_unlock( &count_mutex );
            return(NULL);
        }
        pthread_mutex_unlock( &count_mutex );
    }
}

void *functionCount2()
{
    for(;;)
    {
        pthread_mutex_lock( &count_mutex );
        if( count < COUNT_HALT1 || count > COUNT_HALT2 )
        {
            pthread_cond_signal( &condition_cond );
        }

        count++;
        printf("Counter value functionCount2: %d\n",count);

        if (count >= COUNT_DONE)
        {
            pthread_mutex_unlock( &count_mutex );
            return(NULL);
        }
        pthread_mutex_unlock( &count_mutex );
    }
}
void *functionCount1()
{
    for(;;)
    {
        int my_count;

        pthread_mutex_lock( &count_mutex );
        while( count >= COUNT_HALT1 && count <= COUNT_HALT2 )
        {
            pthread_cond_wait( &condition_cond, &count_mutex );
        }

        count++;
        my_count = count;
        pthread_mutex_unlock( &count_mutex );

        printf("Counter value functionCount1: %d\n", my_count);

        if (my_count >= COUNT_DONE)
            return(NULL);
    }
}

void *functionCount2()
{
    for(;;)
    {
        int my_count;

        pthread_mutex_lock( &count_mutex );
        count++;
        my_count = count;
        pthread_mutex_unlock( &count_mutex );

        printf("Counter value functionCount2: %d\n", my_count);

        if ( my_count < COUNT_HALT1 || my_count > COUNT_HALT2 )
        {
            pthread_cond_signal( &condition_cond );
        }

        if (my_count >= COUNT_DONE)
            return(NULL);
    }
}