#include<atomic> classFoo { private: atomic_bool a = false, b = false; public: Foo() {}
voidfirst(function<void()> printFirst){ // printFirst() outputs "first". Do not change or remove this line. printFirst(); a = true; }
voidsecond(function<void()> printSecond){ while(!a) this_thread::sleep_for(chrono::milliseconds(1)); // printSecond() outputs "second". Do not change or remove this line. printSecond(); b = true; }
voidthird(function<void()> printThird){ while(!b) this_thread::sleep_for(chrono::milliseconds(1)); // printThird() outputs "third". Do not change or remove this line. printThird(); } };
voidfirst(function<void()> printFirst){ // printFirst() outputs "first". Do not change or remove this line. printFirst(); sem_post(&sem_1); }
voidsecond(function<void()> printSecond){ sem_wait(&sem_1); // printSecond() outputs "second". Do not change or remove this line. printSecond(); sem_post(&sem_2); }
voidthird(function<void()> printThird){ sem_wait(&sem_2); // printThird() outputs "third". Do not change or remove this line. printThird(); } };
condition variable
条件变量(Condition Variable)的一般用法是:线程 A 等待某个条件并挂起,直到线程 B 设置了这个条件,并通知条件变量,然后线程 A 被唤醒。这里等待的线程可以是多个,通知线程可以选择一次通知一个(notify_one)或一次通知所有(notify_all)。
voidfoo(function<void()> printFoo){ for (int i = 0; i < n; i++) { while(foo_done) this_thread::yield(); // printFoo() outputs "foo". Do not change or remove this line. printFoo(); foo_done = true; } }
voidbar(function<void()> printBar){ for (int i = 0; i < n; i++) { while(!foo_done) this_thread::yield(); // printBar() outputs "bar". Do not change or remove this line. printBar(); foo_done = false; } } };
voidfoo(function<void()> printFoo){ for (int i = 0; i < n; i++) { sem_wait(&bar_done); // printFoo() outputs "foo". Do not change or remove this line. printFoo(); sem_post(&foo_done); } }
voidbar(function<void()> printBar){ for (int i = 0; i < n; i++) { sem_wait(&foo_done); // printBar() outputs "bar". Do not change or remove this line. printBar(); sem_post(&bar_done); } } };
voidfoo(function<void()> printFoo){ unique_lock<mutex>locker(mtx); for (int i = 0; i < n; i++) { cv.wait(locker, [this] {return !foo_done;}); // printFoo() outputs "foo". Do not change or remove this line. printFoo(); foo_done = true; cv.notify_one(); } }
voidbar(function<void()> printBar){ unique_lock<mutex>locker(mtx); for (int i = 0; i < n; i++) { cv.wait(locker, [this] {return foo_done;}); // printBar() outputs "bar". Do not change or remove this line. printBar(); foo_done = false; cv.notify_one(); } } };
#include<atomic> classZeroEvenOdd { private: int n; atomic_int flag = 0; public: ZeroEvenOdd(int n) { this->n = n; }
// printNumber(x) outputs "x", where x is an integer. voidzero(function<void(int)> printNumber){ for(int i = 1; i <= n; i++){ while(flag) this_thread::yield(); printNumber(0); if(i % 2 == 1){ flag = 1; } else{ flag = 2; } } }
voideven(function<void(int)> printNumber){ for(int i = 2; i <= n; i += 2){ while(flag != 2) this_thread::yield(); printNumber(i); flag = 0; } }
voidodd(function<void(int)> printNumber){ for(int i = 1; i <= n; i += 2){ while(flag != 1) this_thread::yield(); printNumber(i); flag = 0; } } };
// printNumber(x) outputs "x", where x is an integer. voidzero(function<void(int)> printNumber){ for(int i = 1; i <= n; i++){ sem_wait(&s0); printNumber(0); if(i % 2 == 1){ sem_post(&s1); } else{ sem_post(&s2); } } }
voideven(function<void(int)> printNumber){ for(int i = 2; i <= n; i += 2){ sem_wait(&s2); printNumber(i); sem_post(&s0); } }
voidodd(function<void(int)> printNumber){ for(int i = 1; i <= n; i += 2){ sem_wait(&s1); printNumber(i); sem_post(&s0); } } };
condition variable
classZeroEvenOdd { private: int n; mutex mtx; condition_variable cv; int flag = 0; public: ZeroEvenOdd(int n) { this->n = n; }
// printNumber(x) outputs "x", where x is an integer. voidzero(function<void(int)> printNumber){ unique_lock<mutex> locker(mtx); for(int i = 1; i <= n; i++){ cv.wait(locker, [this] {return flag == 0;}); printNumber(0); if(i % 2){ flag = 1; } else{ flag = 2; } cv.notify_all(); } }
voideven(function<void(int)> printNumber){ unique_lock<mutex> locker(mtx); for(int i = 2; i <= n; i+=2){ cv.wait(locker, [this] {return flag == 2;}); printNumber(i); flag = 0; cv.notify_all(); } }
voidodd(function<void(int)> printNumber){ unique_lock<mutex> locker(mtx); for(int i = 1; i <= n; i+=2){ cv.wait(locker, [this] {return flag == 1;}); printNumber(i); flag = 0; cv.notify_all(); } } };