1114. 按序打印
与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();
g = 2;
cv.notify_all();
}
void second(function<void()> printSecond) {
unique_lock<mutex> lck(mtx);
cv.wait(lck, [this]{ return g == 2; });
printSecond();
g = 3;
cv.notify_all();
}
void third(function<void()> printThird) {
unique_lock<mutex> lck(mtx);
cv.wait(lck, [this]{ return g == 3; });
printThird();
g = 1;
cv.notify_all();
}
};
1115. 交替打印FooBar
实现方法比较多.
方法一:condition_variable
class FooBar {
private:
int n;
mutex mtx;
condition_variable cv;
public:
FooBar(int n) {
this->n = n;
}
bool flag{false};
void foo(function<void()> printFoo) {
unique_lock<mutex> lck(mtx);
for (int i = 0; i < n; i++) {
cv.wait(lck, [this]{return !(this->flag);});
printFoo();
this->flag = true;
cv.notify_all();
}
}
void bar(function<void()> printBar) {
unique_lock<mutex> lck(mtx);
for (int i = 0; i < n; i++) {
cv.wait(lck, [this]{return this->flag;});
printBar();
this->flag = false;
cv.notify_all();
}
}
};
方法二:信号量
#include <semaphore.h>
class FooBar {
private:
int n;
sem_t sem_foo;
sem_t sem_bar;
public:
FooBar(int n) {
this->n = n;
sem_init(&sem_foo, 0, 1);
sem_init(&sem_bar, 0, 0);
}
void foo(function<void()> printFoo) {
for (int i = 0; i < n; i++) {
sem_wait(&sem_foo);
printFoo();
sem_post(&sem_bar);
}
}
void bar(function<void()> printBar) {
for (int i = 0; i < n; i++) {
sem_wait(&sem_bar);
printBar();
sem_post(&sem_foo);
}
}
};
方法三:原子变量
class FooBar {
private:
int n;
atomic<bool> flag{false};
public:
FooBar(int n) {
this->n = n;
}
void foo(function<void()> printFoo) {
for (int i = 0; i < n; i++) {
while(flag.load(std::memory_order_acquire)) {
std::this_thread::yield();
}
printFoo();
flag.store(true, std::memory_order_release);
}
}
void bar(function<void()> printBar) {
for (int i = 0; i < n; i++) {
while(!flag.load(std::memory_order_acquire)) {
std::this_thread::yield();
}
printBar();
flag.store(false, std::memory_order_release);
}
}
};
1116. 打印零与奇偶数
方法一:使用信号量sem_t
逻辑比较简单,如果理解信号量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);
}
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
与信号量逻辑差不多,只是改用了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();
}
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();
}
}
};
1195. 交替打印字符串
与上面的题差不多,可以使用多种方法。
方法一:条件变量
使用一个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;
}
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;
printFizz();
g++;
cv.notify_all();
}
}
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();
}
}
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();
}
}
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;
,不加这两句有的线程不会退出。
方法二:原子变量
class FizzBuzz {
private:
int n;
atomic<int> g{1};
public:
FizzBuzz(int n) {
this->n = n;
}
void fizz(function<void()> printFizz) {
while(g.load() <= n) {
if(g % 3 == 0 && g % 5 != 0) {
printFizz();
g++;
}
this_thread::yield();
}
}
void buzz(function<void()> printBuzz) {
while(g.load() <= n) {
if(g % 3 != 0 && g % 5 == 0) {
printBuzz();
g++;
}
this_thread::yield();
}
}
void fizzbuzz(function<void()> printFizzBuzz) {
while(g.load() <= n) {
if(g % 3 == 0 && g % 5 == 0) {
printFizzBuzz();
g++;
}
this_thread::yield();
}
}
void number(function<void(int)> printNumber) {
while(g.load() <= n) {
if(g % 3 != 0 && g % 5 != 0) {
printNumber(g);
g++;
}
this_thread::yield();
}
}
};
方法三:信号量
#include <semaphore.h>
#include <functional>
#include <thread>
using namespace std;
class FizzBuzz {
private:
int n;
int cur;
sem_t sem_fizz;
sem_t sem_buzz;
sem_t sem_fizz_buzz;
sem_t sem_num;
public:
FizzBuzz(int n) {
this->n = n;
cur = 1;
sem_init(&sem_fizz, 0, 0);
sem_init(&sem_buzz, 0, 0);
sem_init(&sem_fizz_buzz, 0, 0);
sem_init(&sem_num, 0, 1);
}
void fizz(function<void()> printFizz) {
while(cur <= n){
sem_wait(&sem_fizz);
if(cur > n) break;
printFizz();
cur++;
sem_post(&sem_num);
}
}
void buzz(function<void()> printBuzz) {
while(cur <= n){
sem_wait(&sem_buzz);
if(cur > n) break;
printBuzz();
cur++;
sem_post(&sem_num);
}
}
void fizzbuzz(function<void()> printFizzBuzz) {
while(cur <= n){
sem_wait(&sem_fizz_buzz);
if(cur > n) break;
printFizzBuzz();
cur++;
sem_post(&sem_num);
}
}
void number(function<void(int)> printNumber) {
while(cur <= n) {
sem_wait(&sem_num);
if(cur>n) break;
if(cur % 3 == 0 && cur % 5 == 0){
sem_post(&sem_fizz_buzz);
}else if(cur % 3 == 0){
sem_post(&sem_fizz);
}else if(cur % 5 == 0){
sem_post(&sem_buzz);
}else{
printNumber(cur);
cur ++;
sem_post(&sem_num);
}
}
sem_post(&sem_fizz);
sem_post(&sem_buzz);
sem_post(&sem_fizz_buzz);
}
};
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)