买票问题,⽣产者-消费者,哲学家就餐问题, 读者写者问题,理发师问题,三个烟⻤问题,使用原⼦操作,semaphore,condition variable中任⼀种同步原语实现。
开始前遇到了一个问题。程序中include了mutex,但是一直提示没有导入。查看了本地库,确实存在mutex文件。原来是安装mingw 时出现了问题,最后参照链接 解决。
买票问题 #include <iostream> #include <thread> #include <condition_variable> #include <mutex> #define MAX_TICKET 100 #define MAX_SELLER 4 using namespace std;mutex mtx; thread sellers[MAX_SELLER]; condition_variable cv; int ticketCnt = MAX_TICKET;void Sell (int id) { while (true ) { unique_lock<mutex> locker (mtx) ; cv.wait (locker, [] { return true ; }); if (ticketCnt == 0 ) break ; cout << "Seller " << id << "\t" << "Ticket " << ticketCnt-- << endl; cv.notify_all (); this_thread::sleep_for (chrono::milliseconds (200 )); } } int main () { for (int i = 0 ; i < MAX_SELLER; ++i) sellers[i] = thread (Sell, i + 1 ); for (auto &seller: sellers) { seller.join (); } return 0 ; }
⽣产者-消费者 #include <iostream> #include <thread> #include <condition_variable> #include <mutex> #define MAX_SIZE 10 #define MAX_OPERATION 100 #define MAX_PRODUCER 3 #define MAX_CONSUMER 3 using namespace std;mutex mtx; thread producers[MAX_PRODUCER]; thread consumers[MAX_CONSUMER]; int productCnt = 0 , operation = 1 ;condition_variable cvConsumer; condition_variable cvProducer; void Producer (int id) { while (true ) { unique_lock<mutex> locker (mtx) ; cvProducer.wait (locker, [] { return productCnt != MAX_SIZE || operation > MAX_OPERATION; }); if (operation > MAX_OPERATION) break ; cout << operation << "\t" << "Producer " << id << "\t" << "product " << ++productCnt << endl; operation++; cvConsumer.notify_all (); this_thread::sleep_for (chrono::milliseconds (200 )); } cout << "Producer " << id << " exits" << endl; } void Consumer (int id) { while (true ) { unique_lock<mutex> locker (mtx) ; cvConsumer.wait (locker, [] { return productCnt != 0 || operation > MAX_OPERATION; }); if (operation > MAX_OPERATION) break ; cout << operation << "\t" << "Consumer " << id << "\t" << "product " << productCnt-- << endl; operation++; cvProducer.notify_all (); this_thread::sleep_for (chrono::milliseconds (200 )); } cout << "Consumer " << id << " exits" << endl; } int main () { for (int i = 0 ; i < MAX_PRODUCER; ++i) producers[i] = thread (Producer, i + 1 ); for (int i = 0 ; i < MAX_CONSUMER; ++i) consumers[i] = thread (Consumer, i + 1 ); for (auto &producer: producers) { producer.join (); } for (auto &consumer: consumers) { consumer.join (); } cout << "products remained: " << productCnt << endl; return 0 ; }
哲学家就餐问题 LeetCode1226,见链接 。
读者写者问题(读者优先) #include <iostream> #include <semaphore.h> #include <thread> #define MAX_READER 3 #define MAX_WRITER 1 using namespace std;thread writers[MAX_WRITER]; thread readers[MAX_READER]; int readerCnt = 0 ;sem_t readerSem, w;void Read (int id, int n) { for (int i = 0 ; i < n; ++i) { sem_wait (&readerSem); readerCnt++; if (readerCnt == 1 ) sem_wait (&w); cout << "reader " << id << endl; sem_post (&readerSem); this_thread::sleep_for (chrono::milliseconds (500 )); sem_wait (&readerSem); readerCnt--; if (readerCnt == 0 ) sem_post (&w); sem_post (&readerSem); } } void Write (int id, int n) { for (int i = 0 ; i < n; ++i) { sem_wait (&w); cout << "writer " << id << endl; sem_post (&w); } } int main () { sem_init (&readerSem, 0 , 1 ); sem_init (&w, 0 , 1 ); for (int i = 0 ; i < MAX_WRITER; ++i) writers[i] = thread (Write, i + 1 , 10 ); for (int i = 0 ; i < MAX_READER; ++i) readers[i] = thread (Read, i + 1 , 20 ); for (auto &writer: writers) writer.join (); for (auto &reader: readers) reader.join (); return 0 ; }
理发师问题 description 理发店里有一位理发师,MAX_CHAIR把供顾客等待理发时坐的椅子。如果没有顾客,理发师睡眠,当顾客到来时叫醒理发师。若理发师正在理发时又有顾客来,有空椅子就坐下,否则离开。代码实现一个理发师,MAX_CUSTOMER个顾客的情况。
solution #include <thread> #include <mutex> #include <iostream> #include <condition_variable> #include <semaphore.h> #define MAX_CHAIR 10 #define MAX_CUSTOMER 20 using namespace std;int empty_chairs = MAX_CHAIR; condition_variable cv_barbers; mutex bar_mtx; thread customers[MAX_CUSTOMER], thread_barber; sem_t chairs;[[noreturn]] void barber () { while (true ) { unique_lock <mutex> lck (bar_mtx); cv_barbers.wait (lck, [] { return MAX_CHAIR - empty_chairs > 0 ; }); sem_wait (&chairs); empty_chairs++; cout << "cut hair" << "\t" << empty_chairs << " Empty chair(s) left." << endl; sem_post (&chairs); this_thread::sleep_for (std::chrono::microseconds (10 )); } } void customer (int i) { sem_wait (&chairs); if (empty_chairs > 0 ) { empty_chairs--; cv_barbers.notify_one (); cout << "customer " << i << " came. " << "\t" << empty_chairs << " Empty chair(s) left." << endl; } else cout << "customer " << i << " came and left." << endl; sem_post (&chairs); } int main () { sem_init (&chairs, 0 , 1 ); thread_barber = thread (barber); for (int i = 0 ; i < MAX_CUSTOMER; ++i) customers[i] = thread (customer, i + 1 ); thread_barber.join (); for (auto &customer: customers) { customer.join (); } return 0 ; }
使用信号量实现对椅子资源的互斥访问。使用condition_variable实现理发师的休息和唤醒。输出如下例。
customer 2 came. 9 Empty chair(s) left. cut hair 10 Empty chair(s) left. customer 3 came. 9 Empty chair(s) left. customer 1 came. 8 Empty chair(s) left. customer 14 came. 7 Empty chair(s) left. customer 5 came. 6 Empty chair(s) left. customer 6 came. 5 Empty chair(s) left. customer 7 came. 4 Empty chair(s) left. customer 8 came. 3 Empty chair(s) left. customer 9 came. 2 Empty chair(s) left. customer 10 came. 1 Empty chair(s) left. customer 11 came. 0 Empty chair(s) left. customer 12 came and left. customer 13 came and left. customer 4 came and left. customer 15 came and left. customer 16 came and left. customer 17 came and left. customer 18 came and left. customer 19 came and left. cut hair 1 Empty chair(s) left. customer 20 came. 0 Empty chair(s) left. cut hair 1 Empty chair(s) left. cut hair 2 Empty chair(s) left. cut hair 3 Empty chair(s) left. cut hair 4 Empty chair(s) left. cut hair 5 Empty chair(s) left. cut hair 6 Empty chair(s) left. cut hair 7 Empty chair(s) left. cut hair 8 Empty chair(s) left. cut hair 9 Empty chair(s) left. cut hair 10 Empty chair(s) left.
三个烟⻤问题 description 三个烟鬼问题实际上就是线程的并发问题:
三个烟鬼,一个有烟草,一个有烟纸,一个有火柴
上帝拿走两个人的材料给一个人,那么你那个人可以抽一支烟
当那个人抽完这只烟的时候,上帝重新做决策
solution #include <thread> #include <atomic> #include <iostream> #include <chrono> #include <random> #define MAX_SMOKE_CNT 15 #define MAX_SMOKERS 3 using namespace std;atomic<int > flag{0 }; atomic<bool > if_exit{false }; thread smokers[MAX_SMOKERS]; void judge () { random_device rd; for (int i = 0 ; i < MAX_SMOKE_CNT; ++i) { while (flag != 0 ) this_thread::yield (); int new_smoker = (int ) ((rd () % 3 ) + 1 ); flag = new_smoker; } if_exit = true ; } void smoke (int id) { while (true ) { while (flag != id) { if (if_exit) return ; else this_thread::yield (); } cout << "smoker " << id << " is smoking..." << endl; this_thread::sleep_for (chrono::milliseconds (500 )); flag = 0 ; } } int main () { for (int i = 0 ; i < MAX_SMOKERS; ++i) smokers[i] = thread (smoke, i + 1 ); thread judger = thread (judge); for (auto &smoker: smokers) { smoker.join (); } judger.join (); }
优雅地使用了C++11中的随机数生成器。