我正在学习多线程。关于
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 3
,1-3
thread1
5)对于count 4-7
,thread2正在运行,thread1
和thread2
之间没有切换
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}}继续进行
答案 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只是理论上的最小值。