三个线程顺序打印ABC 发表于 2022-03-14 | 分类于 多线程/多进程 , 三个线程顺序打印ABC | 三个线程顺序打印ABC 12345678910111213141516171819202122232425262728293031323334353637#include<iostream>#include<vector>#include<thread>#include<condition_variable>using namespace std;mutex m; //互斥锁std::condition_variable cond_var; //创建条件变量对象int num=0;void func(char ch){ int n=ch-'A'; for(int i=0;i<10;i++) { std::unique_lock<std::mutex> mylock(m); cond_var.wait(mylock,[n]{ //调用wait函数,先解锁mylock,然后判断lambda的返回值 return n==num;}); cout<<ch; num=(num+1)%3; mylock.unlock(); cond_var.notify_all(); //唤醒所有等待条件变量的线程。 }}int main(){ vector<thread> pool; pool.push_back(thread(func,'A')); pool.push_back(thread(func,'B')); pool.push_back(thread(func,'C')); for(auto it = pool.begin(); it != pool.end(); it++) { it->join(); } return 0;}/*调用wait时,会执行以下步骤:1、对绑定的unique_lock对象解锁;2、判断调用对象的返回值。如果调用对象返回值为false,则wait就一直阻塞,一直等待被notify唤醒;如果调用对象为true,则会对绑定的unique_lock对象重新上锁,然后wait函数返回,继续执行后续的程序。当wait被notify唤醒时,会先重新对绑定的unique_lock对象上锁,然后执行上面的1、2步骤*/ 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849package mainimport ( "fmt" "sync")var ( mu sync.Mutex // 互斥锁 cond *sync.Cond // 条件变量 num int = 0 // 当前应该打印的字符索引)func printChar(ch rune, wg *sync.WaitGroup) { defer wg.Done() n := int(ch - 'A') for i := 0; i < 10; i++ { mu.Lock() // 等待直到轮到当前goroutine打印 for num != n { cond.Wait() // 释放锁并等待,被唤醒后重新获取锁 } fmt.Print(string(ch)) num = (num + 1) % 3 mu.Unlock() cond.Broadcast() // 唤醒所有等待的goroutine }}func main() { cond = sync.NewCond(&mu) // 创建条件变量对象 var wg sync.WaitGroup wg.Add(3) go printChar('A', &wg) go printChar('B', &wg) go printChar('C', &wg) wg.Wait() fmt.Println() // 换行}/*Go版本说明:1. 使用sync.Cond实现条件变量,类似C++的condition_variable2. cond.Wait()会自动释放锁并等待,被唤醒后重新获取锁3. cond.Broadcast()唤醒所有等待的goroutine,类似notify_all4. 使用sync.WaitGroup等待所有goroutine完成5. 使用for循环检查条件,避免虚假唤醒*/ -------------本文结束 感谢阅读------------- 本文作者: HReina 本文链接: http://hreina.com/2022/03/14/%E4%B8%89%E4%B8%AA%E7%BA%BF%E7%A8%8B%E9%A1%BA%E5%BA%8F%E6%89%93%E5%8D%B0ABC/ 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!