我正在研究一个项目并尝试使用 pthread_cond_wait()
和 pthread_cond_signal()
同步两个线程.
我的代码看起来像这样:
pthread_mutex_t lock_it = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t write_it = PTHREAD_COND_INITIALIZER; int main(int argc, char**argv) { pthread_t t_send_segments, t_recv_acks; pthread_create(&t_send_segments, NULL, send_segments, (void*)NULL); pthread_create(&t_recv_acks, NULL, recv_acks, (void*)NULL); pthread_join(t_recv_acks, (void**)NULL); pthread_mutex_destroy(&lock_it); pthread_cond_destroy(&write_it); } void* send_segments(void *v) { for(;;) { pthread_mutex_lock(&lock_it); printf("s1\n"); printf("s2\n"); pthread_cond_wait(&write_it, &lock_it); printf("s3\n"); printf("s4\n"); printf("s5\n"); pthread_mutex_unlock(&lock_it); } return 0; } void* recv_acks(void *v) { for(;;) { pthread_mutex_lock(&lock_it); printf("r1\n"); pthread_cond_signal(&write_it); printf("r2\n"); pthread_mutex_unlock(&lock_it); } return 0; }
预期的产出是:
s1 s2 r1 s3 s4 s5 s1 s2 r2 r1 s3 s4 s5 (etc)
我的输出根本不遵循这种模式.很明显我在某个地方有一个逻辑错误,但我不知道在哪里.为什么recv_acks()
线程总是在它命中时总是屈服pthread_cond_signal()
- 因为pthread_cond_wait()
总是首先执行(因为我创建线程的顺序)并且cond_wait()
总是执行,因为它在临界区?
该pthread_cond_signal
函数不会导致当前线程产生并且不会释放互斥锁.它所做的就是重新启动一个已通过条件暂停自身的线程pthread_cond_wait
.这只是意味着唤醒的线程可用于调度,它不会导致它立即执行.线程调度程序将在未来的某个时间安排它.
另外,仅仅因为s线程被唤醒并且正在争用互斥锁,这并不意味着它接下来会获得互斥锁.互斥体对于请求它的所有线程不一定公平.根据pthread_mutex
手册页:" pthread_mutex_lock
锁定给定的互斥锁.如果互斥锁当前已解锁,它将被锁定并由调用线程拥有,并pthread_mutex_lock
立即返回." 因此,r-thread可以在其循环中旋转几次,在调度程序换出之前,可以多次解锁并重新锁定互斥锁.这意味着如果调度程序在释放互斥锁的短暂时间内中断r线程,则s线程只会获得互斥锁的机会.
为了实现您想要的输出,两个线程都需要在有条件的情况下控制它们的执行并在挂起之前互相发出信号.但是,这可能是您实际想要对您的真实项目做的,也可能不是.
另一个注意事项:创建线程的顺序并不重要.创建线程不会产生创建线程.因此,主线程可能会在调度之前创建两个线程,并且线程调度程序可以自由地安排其中一个线程执行.如果s-thread确实在您的平台上首先运行,那恰好就是您平台上的实现行为,而不是应该依赖的东西.
我似乎记得读到某个pthread_cond_signal()
实际上并没有导致线程立即产生的地方.由于pthread_cond_signal()
不释放锁,因此调用它的线程必须继续执行,直到它释放锁,然后才会产生并允许发出信号的线程返回pthread_cond_wait()
.
如果是这种情况,那么我认为你的输出会是这样的
s1 s2 r1 r2 s3 s4 s5
等......如果不是这样,你可能需要在你的问题中编辑实际输出以获得准确的答案.