【问题标题】:What if a condition variable signals to a locked thread?如果条件变量向锁定的线程发出信号怎么办?
【发布时间】:2015-07-08 01:46:55
【问题描述】:

在下面的(伪)代码中,cond 可能会唤醒,而它不应该唤醒,无论出于何种原因。所以我在那里放了一个while循环。当它唤醒时,它仍然会消耗锁,因此可以保证在out() 中只有一个线程在做它的工作。

但是,如果 out() 中存在虚假唤醒,同时 in()out() 发出信号,但此时 out() 已经由于虚假唤醒而被锁定,会发生什么情况-向上。那么如果cond 向锁定的线程发出信号会发生什么?

in()
    inLock.lock()
    isEmpty = false
    cond.signal()
    inLock.unlock()

out()
    outLock.lock()
    while isEmpty
        cond.wait(outLock)
    isEmpty = true
    outLock.unlock()


注意

好吧,为了 100% 安全,我知道我可以为 in()out() 使用一个互斥锁,但是当输入和输出同时发生时,我使用的数据结构是 100% 安全的;它是一种队列。而且我认为在填充一些新数据的同时阻止从队列中读取的任何内容是一种性能折衷,反之亦然。

我确实考虑过使用信号量,但问题是很多 C 和 C++ 库出于任何原因都没有实现信号量。

【问题讨论】:

    标签: c multithreading pthreads mutex condition-variable


    【解决方案1】:

    in() 线程设置isEmpty = falseout() 线程测试while (isEmpty) 时,您必须使用相同的互斥锁。否则,可能会发生这种情况:

    1. out()线程测试isEmpty,发现是真的;
    2. in() 线程将 isEmpty 设置为 false 并向条件变量发出信号(但没有人醒来,因为还没有人在等待);
    3. out() 线程调用 cond.wait() 并永远阻塞,尽管队列不再为空。

    请注意,在这个序列中没有虚假唤醒 - 它只是一个普通的旧竞争条件。

    只要您使用与测试 isEmpty 时相同的互斥锁来更新 isEmpty,就不会发生这种交错。

    【讨论】:

      【解决方案2】:

      那么如果 cond 向锁定的线程发出信号会发生什么?

      信号永远丢失。如果在调用pthread_cond_signal 时没有线程在等待信号,则pthread_cond_signal 什么也不做。

      【讨论】:

        【解决方案3】:

        由于isEmpty 正在被两个不同的线程读取和修改,因此在不受保护的情况下访问它是错误的。当您允许 inout 使用不同的锁实例时,这实际上就是您正在做的事情。

        在同一个条件变量上使用不同的锁实例违反了POSIX API for pthread_cond_wait()(强调我的)。

        对并发pthread_cond_wait()pthread_cond_timedwait()使用多个互斥体的影响对同一条件变量的操作未定义;也就是说,当线程等待条件变量时,条件变量将绑定到唯一的互斥体,并且此(动态)绑定在等待返回时结束。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-07-07
          • 1970-01-01
          • 1970-01-01
          • 2021-10-21
          • 2014-07-14
          • 2020-03-13
          • 2017-07-13
          相关资源
          最近更新 更多