条件变量POSIX线程:C / C ++

时间:2013-05-15 07:50:58

标签: c++ c linux multithreading pthreads

我正在学习多线程。关于

http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html#SCHEDULING

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


pthread_mutex_t count_mutex     = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t  condition_var   = PTHREAD_COND_INITIALIZER;



void *functionCount1();
void *functionCount2();

int  count = 0;

#define COUNT_DONE  10
#define COUNT_HALT1  3
#define COUNT_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);

   printf("Final count: %d\n",count);

   exit(0);
}



// Write numbers 1-3 and 8-10 as permitted by functionCount2()

void *functionCount1()
{
   for(;;)
   {
      // Lock mutex and then wait for signal to relase mutex
      pthread_mutex_lock( &count_mutex );



      // Wait while functionCount2() operates on count
      // mutex unlocked if condition varialbe in functionCount2() signaled.

      pthread_cond_wait( &condition_var, &count_mutex );

      count++;

      printf("Counter value functionCount1: %d\n",count);
      pthread_mutex_unlock( &count_mutex );

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



// Write numbers 4-7



void *functionCount2()
{
   for(;;)
    {
       pthread_mutex_lock( &count_mutex );

       if( count < COUNT_HALT1 || count > COUNT_HALT2 )
       {
          // Condition of if statement has been met.
          // Signal to free waiting thread by freeing the mutex.
          // Note: functionCount1() is now permitted to modify "count".

          pthread_cond_signal( &condition_var );
       }
       else
       {
          count++;
          printf("Counter value functionCount2: %d\n",count);
       }



       pthread_mutex_unlock( &count_mutex );

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

我想知道代码的控制流程。

作为pthread_cond_wait - unlocks the mutex and waits for the condition variable cond to be signaled

我对流量控制的理解是

1)创建线程一,两个,并将thread1传递给控件(考虑单核处理器系统)

2)当它在pthread_cond_wait( &condition_var, &count_mutex );例程thread1中遇到void *functionCount1()时 - 它会释放锁并进入等待状态,将控制权传递给thread2 void *functionCount1()

3)在thread2变量count中进行检查,因为它满足count < COUNT_HALT1 || count > COUNT_HALT2 - 它表示thread1并重新启动是增加count

4)重复Steps 2 to 31-3

显示thread1

5)对于count 4-7,thread2正在运行,thread1thread2之间没有切换

6)再次count 8-10重复steps 2-3

我想知道我的理解是否正确? thread1 thread2进入睡眠状态count value 1-3 and 8-10唤醒它(即切换线程)i.e switching between threads happen 5 times thread1

修改

我提出这个问题的主要担心是知道sleep在遇到pthread_cond_wait( &condition_var, &count_mutex );时是否会转到active州,除非发出信号,否则不会thread2 count然后才增加1-3,即它不会一次增加thread2而是增加每个增量,它必须等待来自{{1}}的信号然后它才能增加{{1}}继续进行

3 个答案:

答案 0 :(得分:3)

首先:拿到Butenhof的书,然后研究它。你的页面 引用在一些地方是不正确的,作者显然 不明白自己穿线。

关于你的问题:首先要说的是 你无法知道代码的控制流程。那是 线程的一个特点,在现代处理器上,你会 经常发现线程真正并行运行,只有一个核心 执行一个线程,另一个核心执行另一个并在每个 线程,处理器可以重新安排内存访问 意外的方式。这就是你需要互斥的原因。 (你提到“考虑单核处理系统”,但在 实践中,单核通用系统不存在任何 更多。)

其次,如何安排线程取决于操作 系统。例如,在您的代码中,functionCount2可以运行 直到functionCount1开始之前完成,这将是 意味着functionCount1会永远等待。

第三,pthread_cond_wait中的一个帖子可能会虚假地醒来。 pthread_cond_wait处于循环中是绝对的规则, 它检查你实际等待的任何条件。 也许是这样的:

while ( count > COUNT_HALT1 && count < COUNT_HALT2 ) {
    pthread_cond_wait( &condition_var, &count_mutex );
}

最后,您有时会在某个部分访问count 受互斥锁保护。这是未定义的行为; 所有 必须保护对count的访问。在你的情况下, 锁定和解锁应该在程序之外 循环,两个线程应该等待条件 变量。 (但这显然是一种人为的情况 实践中,几乎总会有一个生产者线程和 消费者线程。)

答案 1 :(得分:2)

在理想世界中,是的,但是,在实践中,并不完全。

您无法预测哪个胎位首先获得控制权。是的,它可能是thread1,但仍然无法保证。这是您代码中的第一个竞赛条件。

thread2获得控制权时,很可能它会在不停止的情况下完成。无论你有多少CPU。原因是无法无条件地yield 。您释放mutex的事实并不意味着any1可以锁定它。这是你代码中的第二个竞赛条件。

因此,thread1将打印11,这是唯一保证的部分。

答案 2 :(得分:1)

1)创建线程。控制没有传递给thread1,它是系统调度程序决定执行哪个线程。两个线程都处于活动状态,两者都应该接收处理器时间,但是顺序未确定。可能有几个上下文切换,你实际上并没有控制它。

2)正确,thread1进入等待状态,thread2继续工作。同样,控制权没有明确传递。

3)是的,thread2通知条件变量,因此thread1将唤醒并尝试重新获取互斥锁。控制不会立即转到thread1。

一般来说,你应该明白你无法真正控制执行哪个线程;它是系统调度程序的工作,可以根据需要放置任意数量的上下文切换。

UPD:使用条件变量,您可以控制多线程环境中任务执行的顺序。所以我认为你的理解或多或少是正确的:thread1正在等待来自thread2的信号的条件变量。当收到信号时,thread1继续执行(在重新获取互斥锁之后)。但是在线程之间切换 - 可能有很多线程,5只是理论上的最小值。