1 Condition
notify和notifyAll()并不释放锁,只是唤醒阻塞在wait方法的线程去参与获得锁的竞争了,但不是马上得到锁,因为锁还在notify和notifyAll()所在线程手里,别人还没释放。如果notify方法后面的代码还有很多,需要这些代码执行完后到scoped_lock锁的作用域结束才会释放scoped_lock锁。
notifyAll使所有阻塞在该std::condition_variable对象上的wait函数的线程统统unblock wait函数并且wait函数继续执行后会去竞争该std::condition_variable对象上的锁。如果其中的某一个竞争中获胜,得到了该std::condition_variable对象上的锁,它就会马上lock住该锁,并且退出wait函数;其它竞争中失败的wait状态等待的线程,则会阻塞在lck.lock()获取锁上,直到之前获取到锁的线程释放掉锁之后才可能获取到锁继续执行。
一个线程在获得mutex锁后,去执行critical section code,但是因为里面的if条件不成立的话则里面的代码就不能被执行到,而且辛辛苦苦获得的mutex锁也要释放掉。只能再等下一次机会获取mutex锁,再去判断条件是否成立。这样的话获得mutex的时间和if之前的代码都是白执行了,效率低下。但是如果用condition的话呢,则在条件不成立的位置可以在当前语句wait,等待外部线程去改变该条件,当外部线程改变了该条件后就通知该线程继续判断条件是否成立,如果成立则接着往下执行。
notify和notifyAll()并不释放锁,只是唤醒阻塞在wait方法的线程去参与获得锁的竞争了,但不是马上得到锁,因为锁还在notify和notifyAll()所在线程手里,别人还没释放。如果notify方法后面的代码还有很多,需要这些代码执行完后到scoped_lock锁的作用域结束才会释放scoped_lock锁。
如果std::condition_variable对象调用了wait方法,该函数会自动调用 lck.unlock()释放锁(注意:此时只是通过unlcok释放掉了mutex,而lck对象还是存在的),然后处于block等待状态。
另外,一旦当前线程获得通知(notified,通常是另外某个线程调用 notify_* 唤醒了当前线程),wait() 函数也是自动调用 lck.lock(),使得 lck 的状态和wait函数之前被调用时相同。
notifyAll使所有阻塞在该std::condition_variable对象上的wait函数的线程统统unblock wait函数并且wait函数继续执行后会去竞争该std::condition_variable对象上的锁。如果其中的某一个竞争中获胜,得到了该std::condition_variable对象上的锁,它就会马上lock住该锁,并且退出wait函数;其它竞争中失败的wait状态等待的线程,则会阻塞在lck.lock()获取锁上,直到之前获取到锁的线程释放掉锁之后才可能获取到锁继续执行。
notify则只是随机选择一个wait状态线程进行通知(如果有多个线程处于wait状态),并使它获得该std::condition_variable对象上的锁,但不通知其他同样在等待被该std::condition_variable对象notify的线程们。当该被通知的线程释放掉了对象上的锁后,如果该对象接下来没有调用用notify或notifyAll语句,则其他wait状态等待的线程由于没有得到该对象的通知,依然继续处在wait状态,直到这个对象发出一个notify或notifyAll。它们等待的是被notify或notifyAll,而不是锁。
当 std::condition_variable 对象的某个wait 函数被调用的时候,当前线程会一直被阻塞,直到另外一个线程在相同的 std::condition_variable 对象上调用了 notification 函数来唤醒当前线程。
一个线程在获得mutex锁后,去执行critical section code,但是因为里面的if条件不成立的话则里面的代码就不能被执行到,而且辛辛苦苦获得的mutex锁也要释放掉。只能再等下一次机会获取mutex锁,再去判断条件是否成立。这样的话获得mutex的时间和if之前的代码都是白执行了,效率低下。但是如果用condition的话呢,则在条件不成立的位置可以在当前语句wait,等待外部线程去改变该条件,当外部线程改变了该条件后就通知该线程继续判断条件是否成立,如果成立则接着往下执行。