【经典进程同步问题】
1.生产者-消费者问题
有一群生产者进程在生产产品,并将这些产品提供给消费者进程去消费。为使生产者进程与消费者进程能并发执行,
在两者之间设置了一个具有n个缓冲区的缓冲池,生产者进程将其所生产的产品放入一个缓冲区中;消费者进程可从
一个缓冲区中取走产品去消费。尽管所有的生产者进程和消费者进程都是以异步方式运行的,但它们之间必须保持
同步,既不允许消费者进程到一个空缓冲区去取产品,也不允许生产者进程向一个已装满产品且尚未被取走的缓冲区
中投放产品。
2.哲学家进餐问题
有五个哲学家共用一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五个碗和五只筷子,他们的生活方式是交替
地进行思考和进餐。平时,一个哲学家进行思考,饥饿时便试图取用其左右最靠近他的筷子,只有在他拿到两只筷子
时才能进餐。进餐毕,放下筷子继续思考。
3.读者-写者问题
一个数据文件或记录可被多个进程共享,我们把只要求读该文件的进程称为“Reader进程”,其他进程则称为“Write进程”。
允许多个进程同时读一个共享对象,因为读操作不会使数据文件混乱。但不允许一个Write进程和其他Reader进程或Writer
进程同时访问共享对象。
一.Mutual exclusion
A mutex object facilitates protection against data races and allows safe synchronization of data between execution agents (30.2.5).
互斥对象有助于防止数据竞争,允许在执行的数据之间安全同步,,允许安全的同步执行中的数据
二.Condition variables
Condition variables provide synchronization primitives used to block a thread until notified by some other thread that some condition is met.
条件变量提供同步原语用于阻塞一个线程直到被其他满足条件的线程通知.
#include <iostream> #include <string> #include <thread> #include <mutex> #include <condition_variable> std::mutex m; std::condition_variable cv; std::string data; bool ready = false; bool processed = false; void worker_thread() { // Wait until main() sends data std::unique_lock<std::mutex> lk(m); cv.wait(lk, []{return ready;}); // after the wait, we own the lock. std::cout << "Worker thread is processing data\n"; data += " after processing"; // Send data back to main() processed = true; std::cout << "Worker thread signals data processing completed\n"; // Manual unlocking is done before notifying, to avoid waking up // the waiting thread only to block again (see notify_one for details) lk.unlock(); cv.notify_one(); } int main() { std::thread worker(worker_thread); data = "Example data"; // send data to the worker thread { std::lock_guard<std::mutex> lk(m); ready = true; std::cout << "main() signals data ready for processing\n"; } cv.notify_one(); // wait for the worker { std::unique_lock<std::mutex> lk(m); cv.wait(lk, []{return processed;}); } std::cout << "Back in main(), data = " << data << '\n'; worker.join(); }