题目地址:
https://leetcode.com/problems/print-zero-even-odd/description/
给定下面的类:
class ZeroEvenOdd {
private:
int n;
public:
ZeroEvenOdd(int n) {
this->n = n;
}
// printNumber(x) outputs "x", where x is an integer.
void zero(function<void(int)> printNumber) {}
void even(function<void(int)> printNumber) {}
void odd(function<void(int)> printNumber) {}
};
同一个这个类的实例会传给三个线程,三个线程分别调用三个函数,要求打印出 010203...0 n 010203...0n 010203...0n这样的字符串。三个函数只能打印符合条件的数字。
要开一个锁让三个线程只能有一个运行,用一个bool变量表示是否应该打印 0 0 0,用另一个int变量表示当前应该打印什么数,一开始让打印 0 0 0的线程运行,然后让它唤醒所有线程,其余线程通过一个condition_variable的判断来决定其是否应该被唤醒。代码如下:
class ZeroEvenOdd {
private:
int n;
int turn, cnt;
mutex mu;
condition_variable cv;
public:
ZeroEvenOdd(int n) {
this->n = n;
turn = 0;
cnt = 1;
}
// printNumber(x) outputs "x", where x is an integer.
void zero(function<void(int)> printNumber) {
while (cnt <= n) {
unique_lock<mutex> ul(mu);
cv.wait(ul, [this] { return turn == 0 || cnt > n; });
if (cnt > n) break;
printNumber(0);
turn = cnt % 2 == 0 ? 2 : 1;
cv.notify_all();
}
}
void even(function<void(int)> printNumber) {
while (cnt <= n) {
unique_lock<mutex> ul(mu);
cv.wait(ul, [this] { return turn == 2 || cnt > n; });
if (cnt > n) break;
printNumber(cnt++);
turn = 0;
cv.notify_all();
}
}
void odd(function<void(int)> printNumber) {
while (cnt <= n) {
unique_lock<mutex> ul(mu);
cv.wait(ul, [this] { return turn == 1 || cnt > n; });
if (cnt > n) break;
printNumber(cnt++);
turn = 0;
cv.notify_all();
}
}
};