简体   繁体   English

如果条件变量发出信号到锁定的线程怎么办?

[英]What if a condition variable signals to a locked thread?

In the (pseudo-)code below, cond might wake up while it shouldn't, for whatever reason. 在下面的(伪)代码中,无论出于何种原因, cond可能会唤醒而不应该唤醒。 So I put a while loop there. 所以我在那里放了一个while循环。 When it does wake up, it will still consume the lock, so it is guaranteed that in out() only one thread is doing its job. 当它确实唤醒时,它仍将消耗锁,因此可以保证在out()只有一个线程正在执行其工作。

But what happens if, while there is a spurious wake-up in out() , at the same time in() signals to out() , however at that very moment out() is already locked because of the spurious wake-up. 但是,如果在out()有一个虚假的唤醒,同时in()out()发出信号,那么会发生什么呢?然而在那个时刻out()已经因为虚假的唤醒而被锁定。 So what happens if the cond signals to a locked thread? 那么如果cond向锁定的线程发出信号会发生什么?

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

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


NOTE 注意

Well, to be 100% safe, I know I can use a single mutex for both in() and out() , but the data structure I'm using is 100% safe when input and output happens at the same time; 好吧,为了100%安全,我知道我可以in()out()使用单个互斥量,但是当输入和输出同时发生时,我使用的数据结构是100%安全的; it is a type of a queue. 它是一种队列。 And I think it is a performance compromise to block anything reading out from the queue while filling in some new data or vice versa. 而且我认为在填充一些新数据时阻止从队列中读出的任何内容都是性能上的妥协,反之亦然。

I did consider using semaphores, but the problems is that so many C and C++ libraries don't implement semaphores for whatever reason. 我确实考虑过使用信号量,但问题是,无论出于何种原因,许多C和C ++库都没有实现信号量。

You have to use the same mutex when the in() thread sets isEmpty = false and the out() thread tests while (isEmpty) . in()线程设置isEmpty = false并且out()线程测试while (isEmpty)时,必须使用相同的互斥锁。 Otherwise, this can happen: 否则,这可能发生:

  1. out() thread tests isEmpty , finds it is true; out()线程测试isEmpty ,发现它是真的;
  2. in() thread sets isEmpty to false and signals the condition variable (but no-one wakes up, beacuse no-one is waiting yet); in()线程将isEmpty设置为false并发出条件变量的信号(但是没有人醒来,因为没有人在等待);
  3. out() thread calls cond.wait() and blocks forever, despite the fact that the queue is not empty anymore. out()线程调用cond.wait()并永远阻塞,尽管队列不再是空的。

Note that in this sequence there hasn't been a spurious wakeup - it's just a plain old race condition. 请注意,在这个序列中没有一个虚假的唤醒 - 它只是一个普通的老竞争条件。

As long as you update isEmpty with the same mutex held as when you test isEmpty , this interleaving can't happen. 只要您使用与测试isEmpty时相同的互斥锁更新isEmpty ,就不会发生此交错。

So what happens if the cond signals to a locked thread? 那么如果cond向锁定的线程发出信号会发生什么?

The signal is lost forever. 信号永远消失。 If no threads are waiting for the signal when pthread_cond_signal is called, then pthread_cond_signal does nothing. 如果没有线程正在等待当信号pthread_cond_signal被调用,然后pthread_cond_signal什么也不做。

Since isEmpty is being read and modified by two different threads, it is an error to access it unprotected. 由于isEmpty正被两个不同的线程读取和修改,因此在不受保护的情况下访问它是错误的。 This is essentially what you are doing when you allow in and out to use different lock instances. 这主要是当你允许你在做什么, inout用不同的锁实例。

Using different lock instances on the same condition variable is a violation of the POSIX API for pthread_cond_wait() (emphasis mine). 在相同的条件变量上使用不同的锁实例违反pthread_cond_wait()POSIX API (强调我的)。

The effect of using more than one mutex for concurrent pthread_cond_wait() or pthread_cond_timedwait() operations on the same condition variable is undefined ; 在同一条件变量上 使用多个互斥锁对并发pthread_cond_wait()pthread_cond_timedwait() 操作的影响是未定义的 ; that is, a condition variable becomes bound to a unique mutex when a thread waits on the condition variable, and this (dynamic) binding ends when the wait returns. 也就是说,当线程等待条件变量时,条件变量将绑定到唯一的互斥锁,并且当等待返回时,此(动态)绑定结束。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM