C++11并发; condition_variable;嘶嘶声,嗡嗡声,嘶嘶声;卡住
C++11 concurrency; condition_variable; fizz, buzz, fizzbuzz; STUCK
我找不到任何错误,程序没有显示任何输出;但是,如果我在看到一些输出后立即在 number() 中引入带有一些打印的 cout,是否会丢失信号?
我启动了 4 个线程,所有线程都使用 unique_lock 公共互斥锁和条件变量。如果我使用信号量,同样的逻辑会起作用,但是当我将它们转换为 c++11 condition_variable 时,我在屏幕上看不到任何输出。线程挂起并等待信号。但是线程 [3] 应该 运行 因为它等待的条件如果为真;当前=1.
#include<iostream>
#include<thread>
#include<mutex>
using namespace std;
class FizzBuzz {
private:
int n;
int curr;
std::mutex mtx;
std::condition_variable cv;
public:
FizzBuzz(int n) {
this->n = n;
curr = 1;
}
// printFizz() outputs "fizz".
void fizz(function<void()> printFizz) {
while(curr <= n) {
std::unique_lock<std::mutex> lck(mtx);
cv.wait(lck, [&]{return (curr <= n && curr % 3 == 0 && curr % 5 != 0);});
printFizz();
curr++;
lck.unlock();
cv.notify_all();
}
}
// printBuzz() outputs "buzz".
void buzz(function<void()> printBuzz) {
while(curr <= n) {
std::unique_lock<std::mutex> lck(mtx);
cv.wait(lck, [&]{return (curr <= n && curr % 3 != 0 && curr % 5 == 0);});
printBuzz();
curr++;
lck.unlock();
cv.notify_all();
}
}
// printFizzBuzz() outputs "fizzbuzz".
void fizzbuzz(function<void()> printFizzBuzz) {
while(curr <= n) {
std::unique_lock<std::mutex> lck(mtx);
cv.wait(lck, [&]{return (curr <= n && curr % 3 == 0 && curr % 5 == 0);});
printFizzBuzz();
curr++;
lck.unlock();
cv.notify_all();
}
}
// printNumber(x) outputs "x", where x is an integer.
void number(function<void(int)> printNumber) {
while(curr <= n) {
std::unique_lock<std::mutex> lck(mtx);
cv.wait(lck, [&]{return (curr <= n && curr % 3 != 0 && curr % 5 != 0);});
printNumber(curr);
curr++;
lck.unlock();
cv.notify_all();
}
}
};
void printFizz (void) {
cout << "Fizz";
};
void printBuzz (void) {
cout << "Buzz";
};
void printFizzBuzz (void) {
cout << "FizzBuzz";
};
void printNumber (int n) {
cout << n;
};
int main(int argc, char* argv[]) {
int num;
sscanf(argv[1], "%d", &num);
std::function<void(void)> f_fizz = printFizz;
std::function<void(void)> f_buzz = printBuzz;
std::function<void(void)> f_fizzbuzz = printFizzBuzz;
std::function<void(int)> f_num = printNumber;
FizzBuzz *objPtr = new FizzBuzz(num);
std::thread threads[4];
threads[0] = std::thread(&FizzBuzz::fizz, objPtr ,f_fizz);
threads[1] = std::thread(&FizzBuzz::buzz,objPtr, f_buzz);
threads[2] = std::thread(&FizzBuzz::fizzbuzz,objPtr, f_fizzbuzz);
threads[3] = std::thread(&FizzBuzz::number,objPtr, f_num);
for (auto& th: threads) th.join();
return 0;
}
notify_all
到达其他线程,但不满足条件curr <=n && ...
。于是,其他线程继续等待,挂了程序。
例如,以下代码将正确终止,因为设置终止标志将唤醒所有线程并让它们中断循环。
#include<iostream>
#include<thread>
#include<mutex>
#include <functional>
#include <condition_variable>
using namespace std;
class FizzBuzz {
private:
int n;
int curr;
std::mutex mtx;
std::condition_variable cv;
bool terminated;
public:
FizzBuzz(int n) {
this->n = n;
curr = 1;
terminated = false;
}
// printFizz() outputs "fizz".
void fizz(function<void()> printFizz) {
while(curr <= n) {
std::unique_lock<std::mutex> lck(mtx);
cv.wait(lck, [&]{return (terminated || (curr % 3 == 0 && curr % 5 != 0));});
if (terminated)
break;
printFizz();
curr++;
lck.unlock();
cv.notify_all();
}
cout << "fizz exiting" << endl;
terminated = true;
}
// printBuzz() outputs "buzz".
void buzz(function<void()> printBuzz) {
while(curr <= n) {
std::unique_lock<std::mutex> lck(mtx);
cv.wait(lck, [&]{return (terminated || (curr % 3 != 0 && curr % 5 == 0));});
if (terminated)
break;
printBuzz();
curr++;
lck.unlock();
cv.notify_all();
}
cout << "buzz exiting" << endl;
terminated = true;
}
// printFizzBuzz() outputs "fizzbuzz".
void fizzbuzz(function<void()> printFizzBuzz) {
while(curr <= n) {
std::unique_lock<std::mutex> lck(mtx);
cv.wait(lck, [&]{return (terminated || (curr % 3 == 0 && curr % 5 == 0));});
if (terminated)
break;
printFizzBuzz();
curr++;
lck.unlock();
cv.notify_all();
}
cout << "fizzbuzz exiting" << endl;
terminated = true;
}
// printNumber(x) outputs "x", where x is an integer.
void number(function<void(int)> printNumber) {
while(curr <= n) {
std::unique_lock<std::mutex> lck(mtx);
cv.wait(lck, [&]{return (terminated || (curr % 3 != 0 && curr % 5 != 0));});
if (terminated)
break;
printNumber(curr);
curr++;
lck.unlock();
cv.notify_all();
}
cout << "number exiting" << endl;
terminated = true;
}
};
void printFizz (void) {
cout << "Fizz" << endl;
};
void printBuzz (void) {
cout << "Buzz" << endl;
};
void printFizzBuzz (void) {
cout << "FizzBuzz" << endl;
};
void printNumber (int n) {
cout << n << endl;
};
int main(int argc, char* argv[]) {
int num;
sscanf(argv[1], "%d", &num);
std::function<void(void)> f_fizz = printFizz;
std::function<void(void)> f_buzz = printBuzz;
std::function<void(void)> f_fizzbuzz = printFizzBuzz;
std::function<void(int)> f_num = printNumber;
FizzBuzz *objPtr = new FizzBuzz(num);
std::thread threads[4];
threads[0] = std::thread(&FizzBuzz::fizz, objPtr ,f_fizz);
threads[1] = std::thread(&FizzBuzz::buzz,objPtr, f_buzz);
threads[2] = std::thread(&FizzBuzz::fizzbuzz,objPtr, f_fizzbuzz);
threads[3] = std::thread(&FizzBuzz::number,objPtr, f_num);
for (auto& th: threads) {
th.join();
}
return 0;
}
我找不到任何错误,程序没有显示任何输出;但是,如果我在看到一些输出后立即在 number() 中引入带有一些打印的 cout,是否会丢失信号?
我启动了 4 个线程,所有线程都使用 unique_lock 公共互斥锁和条件变量。如果我使用信号量,同样的逻辑会起作用,但是当我将它们转换为 c++11 condition_variable 时,我在屏幕上看不到任何输出。线程挂起并等待信号。但是线程 [3] 应该 运行 因为它等待的条件如果为真;当前=1.
#include<iostream>
#include<thread>
#include<mutex>
using namespace std;
class FizzBuzz {
private:
int n;
int curr;
std::mutex mtx;
std::condition_variable cv;
public:
FizzBuzz(int n) {
this->n = n;
curr = 1;
}
// printFizz() outputs "fizz".
void fizz(function<void()> printFizz) {
while(curr <= n) {
std::unique_lock<std::mutex> lck(mtx);
cv.wait(lck, [&]{return (curr <= n && curr % 3 == 0 && curr % 5 != 0);});
printFizz();
curr++;
lck.unlock();
cv.notify_all();
}
}
// printBuzz() outputs "buzz".
void buzz(function<void()> printBuzz) {
while(curr <= n) {
std::unique_lock<std::mutex> lck(mtx);
cv.wait(lck, [&]{return (curr <= n && curr % 3 != 0 && curr % 5 == 0);});
printBuzz();
curr++;
lck.unlock();
cv.notify_all();
}
}
// printFizzBuzz() outputs "fizzbuzz".
void fizzbuzz(function<void()> printFizzBuzz) {
while(curr <= n) {
std::unique_lock<std::mutex> lck(mtx);
cv.wait(lck, [&]{return (curr <= n && curr % 3 == 0 && curr % 5 == 0);});
printFizzBuzz();
curr++;
lck.unlock();
cv.notify_all();
}
}
// printNumber(x) outputs "x", where x is an integer.
void number(function<void(int)> printNumber) {
while(curr <= n) {
std::unique_lock<std::mutex> lck(mtx);
cv.wait(lck, [&]{return (curr <= n && curr % 3 != 0 && curr % 5 != 0);});
printNumber(curr);
curr++;
lck.unlock();
cv.notify_all();
}
}
};
void printFizz (void) {
cout << "Fizz";
};
void printBuzz (void) {
cout << "Buzz";
};
void printFizzBuzz (void) {
cout << "FizzBuzz";
};
void printNumber (int n) {
cout << n;
};
int main(int argc, char* argv[]) {
int num;
sscanf(argv[1], "%d", &num);
std::function<void(void)> f_fizz = printFizz;
std::function<void(void)> f_buzz = printBuzz;
std::function<void(void)> f_fizzbuzz = printFizzBuzz;
std::function<void(int)> f_num = printNumber;
FizzBuzz *objPtr = new FizzBuzz(num);
std::thread threads[4];
threads[0] = std::thread(&FizzBuzz::fizz, objPtr ,f_fizz);
threads[1] = std::thread(&FizzBuzz::buzz,objPtr, f_buzz);
threads[2] = std::thread(&FizzBuzz::fizzbuzz,objPtr, f_fizzbuzz);
threads[3] = std::thread(&FizzBuzz::number,objPtr, f_num);
for (auto& th: threads) th.join();
return 0;
}
notify_all
到达其他线程,但不满足条件curr <=n && ...
。于是,其他线程继续等待,挂了程序。
例如,以下代码将正确终止,因为设置终止标志将唤醒所有线程并让它们中断循环。
#include<iostream>
#include<thread>
#include<mutex>
#include <functional>
#include <condition_variable>
using namespace std;
class FizzBuzz {
private:
int n;
int curr;
std::mutex mtx;
std::condition_variable cv;
bool terminated;
public:
FizzBuzz(int n) {
this->n = n;
curr = 1;
terminated = false;
}
// printFizz() outputs "fizz".
void fizz(function<void()> printFizz) {
while(curr <= n) {
std::unique_lock<std::mutex> lck(mtx);
cv.wait(lck, [&]{return (terminated || (curr % 3 == 0 && curr % 5 != 0));});
if (terminated)
break;
printFizz();
curr++;
lck.unlock();
cv.notify_all();
}
cout << "fizz exiting" << endl;
terminated = true;
}
// printBuzz() outputs "buzz".
void buzz(function<void()> printBuzz) {
while(curr <= n) {
std::unique_lock<std::mutex> lck(mtx);
cv.wait(lck, [&]{return (terminated || (curr % 3 != 0 && curr % 5 == 0));});
if (terminated)
break;
printBuzz();
curr++;
lck.unlock();
cv.notify_all();
}
cout << "buzz exiting" << endl;
terminated = true;
}
// printFizzBuzz() outputs "fizzbuzz".
void fizzbuzz(function<void()> printFizzBuzz) {
while(curr <= n) {
std::unique_lock<std::mutex> lck(mtx);
cv.wait(lck, [&]{return (terminated || (curr % 3 == 0 && curr % 5 == 0));});
if (terminated)
break;
printFizzBuzz();
curr++;
lck.unlock();
cv.notify_all();
}
cout << "fizzbuzz exiting" << endl;
terminated = true;
}
// printNumber(x) outputs "x", where x is an integer.
void number(function<void(int)> printNumber) {
while(curr <= n) {
std::unique_lock<std::mutex> lck(mtx);
cv.wait(lck, [&]{return (terminated || (curr % 3 != 0 && curr % 5 != 0));});
if (terminated)
break;
printNumber(curr);
curr++;
lck.unlock();
cv.notify_all();
}
cout << "number exiting" << endl;
terminated = true;
}
};
void printFizz (void) {
cout << "Fizz" << endl;
};
void printBuzz (void) {
cout << "Buzz" << endl;
};
void printFizzBuzz (void) {
cout << "FizzBuzz" << endl;
};
void printNumber (int n) {
cout << n << endl;
};
int main(int argc, char* argv[]) {
int num;
sscanf(argv[1], "%d", &num);
std::function<void(void)> f_fizz = printFizz;
std::function<void(void)> f_buzz = printBuzz;
std::function<void(void)> f_fizzbuzz = printFizzBuzz;
std::function<void(int)> f_num = printNumber;
FizzBuzz *objPtr = new FizzBuzz(num);
std::thread threads[4];
threads[0] = std::thread(&FizzBuzz::fizz, objPtr ,f_fizz);
threads[1] = std::thread(&FizzBuzz::buzz,objPtr, f_buzz);
threads[2] = std::thread(&FizzBuzz::fizzbuzz,objPtr, f_fizzbuzz);
threads[3] = std::thread(&FizzBuzz::number,objPtr, f_num);
for (auto& th: threads) {
th.join();
}
return 0;
}