c – 为什么pthread_cond_timedwait doc谈论“不可避免的竞赛”?

c – 为什么pthread_cond_timedwait doc谈论“不可避免的竞赛”?,第1张

概述用于pthread_cond_timedwait函数的 The POSIX documentation(IEEE 1003.1,2013)说: It is important to note that when pthread_cond_wait() and pthread_cond_timedwait() return without error, the associated predicat 用于pthread_cond_timeDWait函数的 The POSIX documentation(IEEE 1003.1,2013)说:

It is important to note that when pthread_cond_wait() and pthread_cond_timeDWait() return without error,the associated predicate may still be false. Similarly,when pthread_cond_timeDWait() returns with the timeout error,the associated predicate may be true due to an unavoIDable race between the expiration of the timeout and the predicate state change.

(强调我的)

我们都知道应该在while循环中检查由条件变量控制的谓词的故事,并且可能存在虚假的唤醒.但我的问题是关于这个不可避免的词 – 这是一个强有力的词.为什么这样的比赛无法避免?

请注意,如果这样的比赛不存在,我们可以检查pthread_cond_timeDWait是否超时;而不是再次检查谓词,然后才处理超时条件. (假设,当然,我们仅通过持有的互斥锁发出信号1)和2)当谓词实际发生变化时.)

如果我们被超时唤醒或发出信号,那么用“用户mutex”进行原子检查是不够的?

例如,让我们考虑在POSIX之上构建的条件变量的实现. (省略错误处理和初始化,可以填补明显的空白).

class CV {pthread_mutex_t mtx;pthread_cond_t cv;int waiters; // how many threads are sleePingint wakeups; // how many times this cv got signalledpublic:    CV();~CV();// returns false if it timed out,true otherwisebool wait(Mutex *userMutex,struct timespec *timeout){    pthread_mutex_lock(&mtx);    waiters++;    const int olDWakeups = wakeups;    userMutex->unlock();    int ret; // 0 on success,non-0 on timeout    for (;;) {        ret = pthread_cond_timeDWait(&mtx,&cv,timeout);        if (!(ret == 0 && wakeups == 0))            break; // not spurIoUs    }    if (ret == 0) // not timed out        wakeups--;    pthread_mutex_unlock(&mtx);    userMutex->lock();    pthread_mutex_lock(&mtx);    waiters--;    if (ret != 0 && wakeups > olDWakeups) {        // got a wakeup after a timeout: report the wake instead        ret = 0;        wakeups--;        }    pthread_mutex_unlock(&mtx);    return (ret == 0);}voID wake(){    pthread_mutex_lock(&mtx);    wakeups = min(wakeups + 1,waiters);    pthread_cond_signal(&cv);    pthread_mutex_unlock(&mtx);}};

有可能表明这一点

>如果CV :: wait报告超时,那么我们没有收到信号,因此谓词没有改变;然后
>如果超时到期但我们在返回用户代码并保持用户互斥之前发出信号,那么我们会报告唤醒.

上面的代码是否包含一些严重的错误?如果没有,说比赛是不可避免的是标准错误,还是必须做一些我失踪的其他假设?

解决方法 首先,请注意,这通常是危险的部分:
pthread_mutex_unlock(&mtx);// Trouble is hereuserMutex->lock();pthread_mutex_lock(&mtx);

在评论点,任何事情都可能发生.你没有锁.条件变量的强大之处在于它们始终持有锁或等待.

然后就是手头的问题,不可避免的比赛

if (ret != 0 && wakeups > olDWakeups) {    // got a wakeup after a timeout: report the wake instead    ret = 0;    wakeups--;    }

无法保证一堆pthread_cond_t的等待将被唤醒的顺序,这会对您的计数造成严重破坏

Thread1           Thread2        Thread3{lock userMtx in calling code}{lock mtx}waiters++ (=1)olDWakeups = 0{unlock userMtx }wait {unlock mtx}                  {lock userMtx in calling code}                  {lock mtx}                  signal_all                  wakeups = 1                  {unlock mtx}                  {unlock userMtx in calling code}timeout(unavoID. racecase) {lock mtx}{unlock mtx}                                  {lock userMtx in calling code}                                  {lock mtx}                                  waiters++ (=2)                                  olDWawkupes = 1                                  {unlock userMtx }                                  wait {unlock mtx}                                  timeout {lock mtx}                                  {unlock mtx}                                  {lock userMtx}                                  {lock mtx}                                  waiters-- (=1)                                  wakeups-- (=0)*                                  {unlock mtx}                                  {unlock userMtx in calling code} {lock userMtx} {lock mtx} waiters--(=0) wakeups == olDWakeups (=0) {unlock mtx} {unlock userMtx in calling code}

此时,在线程1上,olDWakeups = wakeups,因此检查不可避免的竞赛案例未能注意到竞赛案例,重新创建了不可避免的竞赛案例.这是由于线程3窃取了针对thread1的信号,使得线程3(真正的超时)看起来像一个信号,而thread1(一个竞争信号/超时)看起来像一个超时

总结

以上是内存溢出为你收集整理的c – 为什么pthread_cond_timedwait doc谈论“不可避免的竞赛”?全部内容,希望文章能够帮你解决c – 为什么pthread_cond_timedwait doc谈论“不可避免的竞赛”?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1239254.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存