与1116题类似,使用condition_variable.
class Foo { public: Foo() { } mutex mtx; atomic<int> g{1}; condition_variable cv; void first(function<void()> printFirst) { unique_lock<mutex> lck(mtx); cv.wait(lck, [this]{ return g == 1; }); // printFirst() outputs "first". Do not change or remove this line. printFirst(); g = 2; cv.notify_all(); } void second(function<void()> printSecond) { unique_lock<mutex> lck(mtx); cv.wait(lck, [this]{ return g == 2; }); // printSecond() outputs "second". Do not change or remove this line. printSecond(); g = 3; cv.notify_all(); } void third(function<void()> printThird) { unique_lock<mutex> lck(mtx); cv.wait(lck, [this]{ return g == 3; }); // printThird() outputs "third". Do not change or remove this line. printThird(); g = 1; cv.notify_all(); } };实现方法比较多.
逻辑比较简单,如果理解信号量sem_t的使用的话。
#include <semaphore.h> class ZeroEvenOdd { private: int n; sem_t zero_s; sem_t odd_s; sem_t even_s; public: ZeroEvenOdd(int n) { this->n = n; sem_init(&zero_s, 0, 1); sem_init(&odd_s, 0, 0); sem_init(&even_s, 0, 0); } // printNumber(x) outputs "x", where x is an integer. void zero(function<void(int)> printNumber) { for(int i = 1; i <= n; i++) { sem_wait(&zero_s); printNumber(0); if(i & 1) { sem_post(&odd_s); } else { sem_post(&even_s); } } } void even(function<void(int)> printNumber) { for(int i = 2; i <= n; i+=2) { sem_wait(&even_s); printNumber(i); sem_post(&zero_s); } } void odd(function<void(int)> printNumber) { for(int i = 1; i <= n; i+=2) { sem_wait(&odd_s); printNumber(i); sem_post(&zero_s); } } };与信号量逻辑差不多,只是改用了mutex。
class ZeroEvenOdd { private: int n; mutex lck[3]; public: ZeroEvenOdd(int n) { this->n = n; lck[0].unlock(); lck[1].lock(); lck[2].lock(); } // printNumber(x) outputs "x", where x is an integer. void zero(function<void(int)> printNumber) { for(int i = 1; i <= n; i++) { lck[0].lock(); printNumber(0); if(i & 1) { lck[2].unlock(); } else { lck[1].unlock(); } } } void even(function<void(int)> printNumber) { for(int i = 2; i <= n; i += 2) { lck[1].lock(); printNumber(i); lck[0].unlock(); } } void odd(function<void(int)> printNumber) { for(int i = 1; i <= n; i += 2) { lck[2].lock(); printNumber(i); lck[0].unlock(); } } };与上面的题差不多,可以使用多种方法。
使用一个atomic<int> 表示当前计数,看其能否被3和5整除。
class FizzBuzz { private: int n; mutex mtx; condition_variable cv; atomic<int> g{1}; public: FizzBuzz(int n) { this->n = n; } // printFizz() outputs "fizz". void fizz(function<void()> printFizz) { while(g <= n) { unique_lock<mutex> lck(mtx); cv.wait(lck, [this]{ return (g > n) || (g % 3 == 0 && g % 5 != 0); }); if(g > n) break; //注意这里和上面wait函数中的条件 printFizz(); g++; cv.notify_all(); } } // printBuzz() outputs "buzz". void buzz(function<void()> printBuzz) { while(g <= n) { unique_lock<mutex> lck(mtx); cv.wait(lck, [this]{ return (g > n) || (g % 5 == 0 && g % 3 != 0); }); if(g > n) break; printBuzz(); g++; cv.notify_all(); } } // printFizzBuzz() outputs "fizzbuzz". void fizzbuzz(function<void()> printFizzBuzz) { while(g <= n) { unique_lock<mutex> lck(mtx); cv.wait(lck, [this]{ return (g > n) || (g % 3 == 0 && g % 5 == 0); }); if(g > n) break; printFizzBuzz(); g++; cv.notify_all(); } } // printNumber(x) outputs "x", where x is an integer. void number(function<void(int)> printNumber) { while(g <= n) { unique_lock<mutex> lck(mtx); cv.wait(lck, [this]{ return (g > n) || (g % 3 != 0 && g % 5 != 0); }); if(g > n) break; printNumber(g); g++; cv.notify_all(); } } };需要注意wait函数中的一个条件(g > n),以及:if(g > n) break;,不加这两句有的线程不会退出。