题目链接:https://leetcode-cn.com/problems/print-in-order/
class Foo {
public:
Foo() {
mu1.lock();
mu2.lock();
}
void first(function printFirst) {
// printFirst() outputs "first". Do not change or remove this line.
printFirst();
mu1.unlock();
}
void second(function printSecond) {
lock_guard guard(mu1);
// printSecond() outputs "second". Do not change or remove this line.
printSecond();
mu2.unlock();
}
void third(function printThird) {
lock_guard guard(mu2);
lock_guard guard2(mu1);
// printThird() outputs "third". Do not change or remove this line.
printThird();
}
private:
std::mutex mu1,mu2;
};
可以看作是2把锁,初始时都上锁,printFirst在任何时候可执行。执行结束后开锁1
printSecond只有在锁1开锁后才可以执行,执行时锁锁1,执行结束后开锁2,自动开锁1
printThird只有在锁2开锁后,锁1开锁后才可以执行,执行时锁锁1和2,执行结束后自动开锁1和2. 注意这里上锁不可以先1后2,可能发生死锁。
或者
class Foo {
public:
Foo() {
mu1.lock();
mu2.lock();
}
void first(function printFirst) {
// printFirst() outputs "first". Do not change or remove this line.
printFirst();
mu1.unlock();
}
void second(function printSecond) {
mu1.lock();
// printSecond() outputs "second". Do not change or remove this line.
printSecond();
mu2.unlock();
}
void third(function printThird) {
mu2.lock();
// printThird() outputs "third". Do not change or remove this line.
printThird();
}
private:
std::mutex mu1,mu2;
};
第二个更好点
class Foo {
public:
Foo() {
}
void first(function printFirst) {
// printFirst() outputs "first". Do not change or remove this line.
printFirst();
counter+=1;
cond1.notify_one();
}
void second(function printSecond) {
unique_lock lk(mu);
cond1.wait(lk,[this](){return counter==2;});
// printSecond() outputs "second". Do not change or remove this line.
printSecond();
counter+=1;
cond2.notify_one();
}
void third(function printThird) {
unique_lock lk(mu);
cond2.wait(lk,[this](){return counter==3;});
// printThird() outputs "third". Do not change or remove this line.
printThird();
}
private:
std::mutex mu;
std::condition_variable cond1;
std::condition_variable cond2;
int counter=1;
};
wait的第二个参数是一个lambda函数
题目链接:https://leetcode-cn.com/problems/print-foobar-alternately/
class FooBar {
private:
int n;
std::mutex mu1,mu2;
public:
FooBar(int n) {
this->n = n;
mu2.lock();
}
void foo(function printFoo) {
for (int i = 0; i < n; i++) {
mu1.lock();
// printFoo() outputs "foo". Do not change or remove this line.
printFoo();
mu2.unlock();
}
}
void bar(function printBar) {
for (int i = 0; i < n; i++) {
mu2.lock();
// printBar() outputs "bar". Do not change or remove this line.
printBar();
mu1.unlock();
}
}
};
class FooBar {
private:
int n;
std::condition_variable cond1,cond2;
std::mutex mu;
bool var=false;
public:
FooBar(int n) {
this->n = n;
}
void foo(function printFoo) {
for (int i = 0; i < n; i++) {
unique_lock lk(mu);
cond1.wait(lk,[this](){return !var;});
// printFoo() outputs "foo". Do not change or remove this line.
printFoo();
var=true;
cond2.notify_one();
}
}
void bar(function printBar) {
for (int i = 0; i < n; i++) {
unique_lock lk(mu);
cond2.wait(lk,[this](){return var;});
// printBar() outputs "bar". Do not change or remove this line.
printBar();
var=false;
cond1.notify_one();
}
}
};
注意有一个bool值。
题目链接:https://leetcode-cn.com/problems/print-zero-even-odd/
class ZeroEvenOdd {
private:
int n;
std::mutex mu1,mu2,mu3;
public:
ZeroEvenOdd(int n) {
this->n = n;
mu2.lock();
mu3.lock();
}
// printNumber(x) outputs "x", where x is an integer.
void zero(function printNumber) {
for(int i=1;i<=n;i++)
{
mu1.lock();
printNumber(0);
//奇数
if(i%2)
mu3.unlock();
//偶数
else
mu2.unlock();
}
}
void even(function printNumber) {
for(int i=2;i<=n;i+=2)
{
mu2.lock();
printNumber(i);
mu1.unlock();
}
}
void odd(function printNumber) {
for(int i=1;i<=n;i+=2)
{
mu3.lock();
printNumber(i);
mu1.unlock();
}
}
};
class ZeroEvenOdd {
private:
int n;
std::mutex mu;
std::condition_variable cv_zero,cv_odd,cv_even;
bool bzero,bodd;
public:
ZeroEvenOdd(int n) {
this->n = n;
bzero=true;
bodd=false;
}
// printNumber(x) outputs "x", where x is an integer.
void zero(function printNumber) {
unique_lock lk(mu);
for(int i=1;i<=n;i++)
{
cv_zero.wait(lk,[this](){return bzero;});
printNumber(0);
//奇数
if(i%2)
{
cv_odd.notify_one();
bodd=true;
}
else
cv_even.notify_one();
bzero=false;
}
}
void even(function printNumber) {
unique_lock lk(mu);
for(int i=2;i<=n;i+=2)
{
cv_even.wait(lk,[this](){return !bzero&&!bodd;});
printNumber(i);
bzero=true;
bodd=true;
cv_zero.notify_one();
}
}
void odd(function printNumber) {
unique_lock lk(mu);
for(int i=1;i<=n;i+=2)
{
cv_odd.wait(lk,[this](){return !bzero&&bodd;});
printNumber(i);
bzero=true;
bodd=false;
cv_zero.notify_one();
}
}
};
注意那2个布尔值。
题目链接:https://leetcode-cn.com/problems/building-h2o/
class H2O {
public:
H2O() {
}
void hydrogen(function releaseHydrogen) {
// releaseHydrogen() outputs "H". Do not change or remove this line.
std::unique_lock lk(m);
cv.wait(lk, [this](){return h_count <2;});
releaseHydrogen();
++h_count;
if (h_count == 2 && o_count == 1){
o_count = 0;
h_count = 0;
}
if(h_count==2)
cv.notify_all();
}
void oxygen(function releaseOxygen) {
// releaseOxygen() outputs "O". Do not change or remove this line.
std::unique_lock lk(m);
cv.wait(lk, [this](){return o_count <1&&h_count==2;});
releaseOxygen();
++o_count;
if (h_count == 2 && o_count == 1){
o_count = 0;
h_count = 0;
}
cv.notify_one();
}
private:
std::mutex m;
std::condition_variable cv;
int o_count = 0;
int h_count = 0;
};