线程同步除了使用mutex
,还可以使用conditional variables
(下列内容摘自FreeBSD Device Drivers):
Condition variables synchronize the execution of two or more threads based upon the value of an object. In contrast, locks synchronize threads by controlling their access to objects.
Condition variables are used in conjunction with locks to “block” threads until a condition is true. It works like this: A thread first acquires the foo lock. Then it examines the condition. If the condition is false, it sleeps on the bar condition variable. While asleep on bar , threads relinquish foo . A thread that causes the condition to be true wakes up the threads sleeping on bar . Threads woken up in this manner reacquire foo before proceeding.
此外,使用conditional variables
必然涉及到lock
,以下是关于lock
的规则(下列内容摘自FreeBSD Kernel Developer’s Manual):
The lock argument is a pointer to either mutex(9), rwlock(9), or sx(9) lock. A mutex(9) argument must be initialized with MTX_DEF and not MTX_SPIN. A thread must hold lock before calling cvwait(), cvwaitsig(), cvwaitunlock(), cvtimedwait(), or cvtimedwaitsig(). When a thread waits on a condition, lock is atomically released before the thread is blocked, then reacquired before the function call returns. In addition, the thread will fully drop the Giant mutex (even if recursed) while the it is suspended and will reacquire the Giant mutex before the function returns. The cvwaitunlock() function does not reacquire the lock before returning. Note that the Giant mutex may be specified as lock. However, Giant may not be used as lock for the cvwaitunlock() function. All waiters must pass the same lock in con- junction with cvp.
简而言之,即线程在调用cv_wait()
等系列函数检查condition
变成true
时,它必须已经获得lock
。在cv_wait()
中,线程会先释放lock
,然后阻塞在这里等待condition
变成true
,在从cv_wait()
返回后,又重新获得lock
。要注意,cv_wait_unlock()
函数返回是不会重新获得lock
。