实际上,该示例并未显示该问题,但作为一般原则,当有两条指令时,存在竞争条件。
这是一个希望能说明问题的例子。
假设您自己管理互斥锁,并且您有两个线程thread#1和thread#2:
- thread#1需要修改一些共享状态
- 它获取互斥体并更改状态
- 它释放互斥体并在继续之前等待某些事情发生
这是一些代码:
pthread_mutex_lock(&mutex);
// change state
pthread_mutex_unlock(&mutex);
pthread_cond_wait(&cond);
还有更多:
- 线程#2等待互斥体,更改共享状态并使用条件变量向线程#1 发出信号,让线程#1在继续之前有机会做某事
这是代码:
pthread_mutex_lock(&mutex);
// change state
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);
这是一个令人讨厌的场景:
- thread#1获取锁并改变共享状态
- thread#1释放锁,
pthread_mutex_unlock(&mutex)
, 并被抢占
- 线程#2获取锁,
pthread_mutex_lock(&mutex)
更改状态,解锁,发出信号并被抢占
- 线程#1再次被调度并等待条件,
pthread_cond_wait(&cond)
您有一个问题可能会升级:
- 信号已丢失:它本身可能或多或少取决于您的应用程序
- 但即使信号本身并不重要,线程#1现在也卡在等待已经发生的信号
- 即使线程#1没有做一些重要的事情,如果后面的线程#2等待线程#1 ,你也可能会出现死锁
因此,为了避免这个问题,线程#1必须在任何其他线程有机会发出条件信号之前在释放锁时立即等待。
恕我直言,它更多的是解锁/等待转换,而不是需要原子的唤醒/锁定转换。
我很好奇唤醒/锁定转换绝对需要原子的场景......
希望这可以帮助。