1 背景
力扣1116题 打印零和奇偶数。
2 方法
方法1:原子操作
class ZeroEvenOdd {
private:
int n;
atomic<int> flag = 0;
public:
ZeroEvenOdd(int n) {
this->n = n;
}
// printNumber(x) outputs "x", where x is an integer.
void zero(function<void(int)> printNumber) {
for (int i = 1; i <= n; ++i) {
while (flag != 0) {
this_thread::yield();
}
printNumber(0);
if (i % 2 == 0) {
flag = 2;
} else {
flag = 1;
}
}
}
void even(function<void(int)> printNumber) {
for (int i = 2; i <= n; i += 2) {
while (flag != 2) {
this_thread::yield();
}
printNumber(i);
flag = 0;
}
}
void odd(function<void(int)> printNumber) {
for (int i = 1; i <= n; i += 2) {
while (flag != 1) {
this_thread::yield();
}
printNumber(i);
flag = 0;
}
}
};
方法2:互斥锁和变量控制
class ZeroEvenOdd {
private:
int n;
mutex m;
condition_variable cv;
int flag = 0;
public:
ZeroEvenOdd(int n) {
this->n = n;
}
// printNumber(x) outputs "x", where x is an integer.
void zero(function<void(int)> printNumber) {
for (int i = 1; i <= n; ++i) {
unique_lock<mutex> lock(m);
cv.wait(lock, [&] {return flag == 0;});
printNumber(0);
if (i % 2 == 0) {
flag = 2;
} else {
flag = 1;
}
cv.notify_one();
}
}
void even(function<void(int)> printNumber) {
for (int i = 2; i <= n; i += 2) {
unique_lock<mutex> lock(m);
cv.wait(lock, [&] {return flag == 2;});
printNumber(i);
flag = 0;
cv.notify_one();
}
}
void odd(function<void(int)> printNumber) {
for (int i = 1; i <= n; i += 2) {
unique_lock<mutex> lock(m);
cv.wait(lock, [&] {return flag == 1;});
printNumber(i);
flag = 0;
cv.notify_one();
}
}
};
方法3:信号量
#include <semaphore.h>
class ZeroEvenOdd {
private:
int n;
sem_t printOdd, printEven, numDone;
public:
ZeroEvenOdd(int n) {
this->n = n;
sem_init(&printOdd, 0, 0);
sem_init(&printEven, 0, 0);
sem_init(&numDone, 0, 1);
}
// printNumber(x) outputs "x", where x is an integer.
void zero(function<void(int)> printNumber) {
for (int i = 1; i <= n; ++i) {
sem_wait(&numDone);
printNumber(0);
if (i % 2 == 0) {
sem_post(&printEven);
} else {
sem_post(&printOdd);
}
}
}
void even(function<void(int)> printNumber) {
for (int i = 2; i <= n; i += 2) {
sem_wait(&printEven);
printNumber(i);
sem_post(&numDone);
}
}
void odd(function<void(int)> printNumber) {
for (int i = 1; i <=n; i += 2) {
sem_wait(&printOdd);
printNumber(i);
sem_post(&numDone);
}
}
};