1. 三个线程交替打印10次ABC
#include <iostream>
#include <thread>
#include <condition_variable>
std::mutex mtx;
std::condition_variable cv;
int ready = 1; // 1打印A,2打印B,3打印C
void printA() {
std::unique_lock<std::mutex> a_lock(mtx);
int i = 0;
while (i < 10) {
while (ready != 1) cv.wait(a_lock); // 不满足条件,就会阻塞在这
std::cout << std::this_thread::get_id() << " A" << std::endl;
i++;
ready = 2; // A打印完了该打印B了,就改为2
cv.notify_all();
}
}
void printB() {
std::unique_lock<std::mutex> b_lock(mtx);
int i = 0;
while (i < 10) {
while (ready != 2) cv.wait(b_lock);
std::cout << std::this_thread::get_id() << " B" << std::endl;
i++;
ready = 3;
cv.notify_all();
}
}
void printC() {
std::unique_lock<std::mutex> c_lock(mtx);
int i = 0;
while (i < 10) {
while (ready != 3) cv.wait(c_lock);
std::cout << std::this_thread::get_id() << " C" << std::endl;
i++;
ready = 1;
cv.notify_all();
}
}
int main()
{
std::thread thread_a(printA);
std::thread thread_b(printB);
std::thread thread_c(printC);
thread_a.join();
thread_b.join();
thread_c.join();
return 0;
}
2. 两个线程交替打印奇偶数
#include <iostream>
#include <thread>
std::mutex mtx;
// 使用锁的版本
int x = 1;
void printOdd() {
while (1) {
mtx.lock();
if (x % 2 != 0) {
std::cout << std::this_thread::get_id() << " " << x << std::endl;
x++;
}
mtx.unlock();
if (x >= 10) break;
}
}
void printEven(){
while (1) {
mtx.lock();
if (x % 2 == 0) {
std::cout << std::this_thread::get_id() << " " << x << std::endl;
x++;
}
mtx.unlock();
if (x >= 10) break;
}
}
int main()
{
std::thread thread_odd(printOdd);
std::thread thread_even(printEven);
thread_odd.join();
thread_even.join();
return 0;
}
#include <iostream>
#include <thread>
#include <condition_variable>
// 使用条件变量的版本
int x = 1;
const int target = 10;
void printOdd() {
std::unique_lock<std::mutex> odd_lock(mtx);
while (x < target ) {
while (x % 2 == 0) cv.wait(odd_lock);
std::cout << std::this_thread::get_id() << " " << x << std::endl;
x++;
cv.notify_all();
}
}
void printEven(){
std::unique_lock<std::mutex> even_lock(mtx);
while (x < target ) {
while (x % 2 != 0) cv.wait(even_lock);
std::cout << std::this_thread::get_id() << " " << x << std::endl;
x++;
cv.notify_all();
}
}
int main()
{
std::thread thread_odd(printOdd);
std::thread thread_even(printEven);
thread_odd.join();
thread_even.join();
return 0;
}
注意两个版本判断退出的时候,都不能带有等于。比如条件变量版本,while的条件是x<target而不是x<=target,如果是<=,会输出1到11。这是因为如果带有等号,最后一次会阻塞在循环里,那么就会多输出一次。
比如printOdd打印9以后,x变成10,判断while(x<=10)满足,就阻塞在while (x % 2 != 0) cv.wait(even_lock);这一句。然后printEven打印10以后,x变成11,退出循环。但唤醒了阻塞在printOdd的线程,这时候从阻塞的地方开始执行,判断while (x % 2 != 0)不满足,就不会阻塞,就往下执行,于是打印出了x=11。