基于Pthreads线程库的实现
g++ your_program.cpp -lpthread
编译时确保链接了Pthreads库.
#include <pthread.h>
#include <iostream>
#include <unistd.h>// 全局变量,用于控制打印顺序
int turn = 0;
// 定义互斥锁和条件变量
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;void* printA(void* arg) {for (int i = 0; i < 10; i++) {pthread_mutex_lock(&lock);while (turn != 0) {pthread_cond_wait(&cond, &lock);}std::cout << "A ";turn = 1;pthread_cond_broadcast(&cond);pthread_mutex_unlock(&lock);}return NULL;
}void* printB(void* arg) {for (int i = 0; i < 10; i++) {pthread_mutex_lock(&lock);while (turn != 1) {pthread_cond_wait(&cond, &lock);}std::cout << "B ";turn = 2;pthread_cond_broadcast(&cond);pthread_mutex_unlock(&lock);}return NULL;
}void* printC(void* arg) {for (int i = 0; i < 10; i++) {pthread_mutex_lock(&lock);while (turn != 2) {pthread_cond_wait(&cond, &lock);}std::cout << "C ";turn = 0;pthread_cond_broadcast(&cond);pthread_mutex_unlock(&lock);}return NULL;
}int main() {pthread_t t1, t2, t3;pthread_create(&t1, NULL, printA, NULL);pthread_create(&t2, NULL, printB, NULL);pthread_create(&t3, NULL, printC, NULL);pthread_join(t1, NULL);pthread_join(t2, NULL);pthread_join(t3, NULL);pthread_mutex_destroy(&lock);pthread_cond_destroy(&cond);return 0;
}
互斥锁和条件变量
#include <iostream>
#include <vector>
#include <thread>
#include <mutex>
using namespace std;class PrintABC {
public:PrintABC(int count) : count_(count) { }void printA () {for (int i = 0; i < count_; ++i) {std::unique_lock<std::mutex> lock(mtx_);//等待turn_变为0cv_.wait(lock, [this]() { return turn_ == 0; });std::cout << "a" << endl;//设置下一个轮次为1,并通知等待的线程turn_ = 1;cv_.notify_all();}}void printB () {for (int i = 0; i < count_; ++i) {std::unique_lock<std::mutex> lock(mtx_);//等待turn_变为0cv_.wait(lock, [this]() { return turn_ == 1; });std::cout << "b" << endl;//设置下一个轮次为1,并通知等待的线程turn_ = 2;cv_.notify_all();}}void printC () {for (int i = 0; i < count_; ++i) {std::unique_lock<std::mutex> lock(mtx_);//等待turn_变为0cv_.wait(lock, [this]() { return turn_ == 2; });std::cout << "c" << endl;//设置下一个轮次为1,并通知等待的线程turn_ = 0;cv_.notify_all();}}
private:std::mutex mtx_;std::condition_variable cv_;int turn_ = 0; //控制打印顺序,0代表打印a,1代表打印b,2代表打印c,int count_; //打印次数
};int main () {int printCount = 10; //设定打印次数PrintABC printABC(printCount);std::thread t1(&PrintABC::printA, &printABC);std::thread t2(&PrintABC::printB, &printABC);std::thread t3(&PrintABC::printC, &printABC);t1.join();t2.join();t3.join();return 0;
}
原子变量
无锁实现控制打印顺序,但会占用更多的CPU资源,因为线程在等待时处于忙等(busy-waiting)状态。
#include <iostream>
#include <thread>
#include <atomic>volatile std::atomic<int> turn(0);void printA(int count) {for (int i = 0; i < count; ++i) {while(turn != 0); // 忙等std::cout << "a";turn = 1;}
}void printB(int count) {for (int i = 0; i < count; ++i) {while(turn != 1); // 忙等std::cout << "b";turn = 2;}
}void printC(int count) {for (int i = 0; i < count; ++i) {while(turn != 2); // 忙等std::cout << "c";turn = 0;}
}int main() {int count = 10;std::thread a(printA, count);std::thread b(printB, count);std::thread c(printC, count);a.join();b.join();c.join();std::cout << "\n";return 0;
}
信号量
C++20之后引入的库,才使得C++语言级别的信号量实现,
编译的时候记得加一个-std=c++20
#include <iostream>
#include <thread>
#include <semaphore>std::counting_semaphore semA(1); // 初始计数为1,A可以立即打印
std::counting_semaphore semB(0); // 初始计数为0,B需要等待A释放
std::counting_semaphore semC(0); // 初始计数为0,C需要等待B释放void printA(int count) {for (int i = 0; i < count; ++i) {semA.acquire();std::cout << "a" << std::endl;semB.release();}
}void printB(int count) {for (int i = 0; i < count; ++i) {semB.acquire();std::cout << "b" << std::endl;semC.release();}
}void printC(int count) {for (int i = 0; i < count; ++i) {semC.acquire();std::cout << "c" << std::endl;semA.release();}
}int main() {int count = 10; // 每个线程打印10次std::thread a(printA, count);std::thread b(printB, count);std::thread c(printC, count);a.join();b.join();c.join();std::cout << "\n";return 0;
}