C ++多线程中的锁和条件变量问题
Issue with lock and condition variable in c++ multithreading
我正在尝试在 C++ 中实现一个简单的多线程示例(Windows 10,Visual Studio Express)。
我有计算 z = x * x 的线程 T1,其中 x 和 z 是全局变量。
线程 T2 显示 z.
我想使用锁和条件变量。
由于某种原因,执行 在 T1 未被阻止时卡住 (在 cv.wait 之后,可能在 while 循环中——高 CPU 使用率)。但是当我在 main() 中的 cv.notify_one();
之前添加一些代码(我尝试使用 cout << "x" << endl;
)时,这个 不会发生。很奇怪。
预先感谢您的帮助!
这是代码。我删除了我用来杀死线程的部分,因为我没有接触到算法的那部分——问题在之前。
#include "stdafx.h"
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;
mutex m;
condition_variable cv;
bool datax = 0, dataz = 0, zPrinted = 0;
void T1(const int& x, int& z)
{
do {
unique_lock<mutex> lk(m);
cv.wait(lk, [] {return (datax); });
if (datax) {
z = x * x;
datax = 0;
dataz = 1;
lk.unlock();
while (dataz)
cv.notify_one();
}
} while (1);
}
void T2(const int& z)
{
do {
unique_lock<mutex> lk(m);
cv.wait(lk, [] {return (dataz); });
if (dataz) {
cout << "z = " << z << endl;
dataz = 0;
zPrinted = 1;
lk.unlock();
while (zPrinted)
cv.notify_one();
}
} while (1);
}
int main()
{
int x, z;
char c;
thread threadT1(T1, cref(x), ref(z));
thread threadT2(T2, cref(z));
do {
unique_lock<mutex> lk(m);
cout << "Enter x: ";
cin >> x;
datax = 1;
lk.unlock();
while (datax) {
cv.notify_one();
}
cv.wait(lk, [] {return zPrinted; });
zPrinted = 0;
cout << "Continue? (y/n): ";
cin >> c;
} while (c == 'y');
return 0;
}
问题出在这里:
lk.unlock();
while (datax) {
cv.notify_one();
}
cv.wait(lk, [] {return zPrinted; }); // <-- waiting on unlocked mutex
zPrinted = 0;
您正在等待一个解锁的互斥体,这是未定义的行为see here under notes。
除了上面指出的等待解锁互斥体的问题:
cv.wait(lk, [] {return zPrinted; });
您有未重新加入的线程,并且是 运行 无限循环。这是一个带有模组的工作版本来解决这些问题:
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;
mutex m;
condition_variable cv;
bool datax = 0, dataz = 0, zPrinted = 0;
bool kill = 0;
void T1(const int& x, int& z)
{
do {
unique_lock<mutex> lk(m);
cv.wait(lk, [] {return (datax+kill); });
if (kill) return;
if (datax) {
z = x * x;
datax = 0;
dataz = 1;
lk.unlock();
while (dataz)
cv.notify_one();
}
} while (1);
}
void T2(const int& z)
{
do {
unique_lock<mutex> lk(m);
cv.wait(lk, [] {return (dataz+kill); });
if (kill) return;
if (dataz) {
cout << "z = " << z << endl;
dataz = 0;
zPrinted = 1;
lk.unlock();
while (zPrinted)
cv.notify_one();
}
} while (1);
}
int main()
{
int x, z;
char c;
thread threadT1(T1, cref(x), ref(z));
thread threadT2(T2, cref(z));
do {
{
unique_lock<mutex> lk(m);
cout << "Enter x: ";
cin >> x;
datax = 1;
lk.unlock();
while (datax)
cv.notify_one();
}
{
unique_lock<mutex> lk(m);
cv.wait(lk, [] {return zPrinted; });
lk.unlock();
}
zPrinted = 0;
cout << "Continue? (y/n): ";
cin >> c;
} while (c == 'y');
kill = 1;
cv.notify_all();
threadT1.join();
threadT2.join();
return 0;
}
如您所见,我引入了一个新变量 "kill",当设置为 1 时,会导致两个线程退出它们的无限循环,这样它们就可以连接起来。
我正在尝试在 C++ 中实现一个简单的多线程示例(Windows 10,Visual Studio Express)。
我有计算 z = x * x 的线程 T1,其中 x 和 z 是全局变量。 线程 T2 显示 z.
我想使用锁和条件变量。
由于某种原因,执行 在 T1 未被阻止时卡住 (在 cv.wait 之后,可能在 while 循环中——高 CPU 使用率)。但是当我在 main() 中的 cv.notify_one();
之前添加一些代码(我尝试使用 cout << "x" << endl;
)时,这个 不会发生。很奇怪。
预先感谢您的帮助!
这是代码。我删除了我用来杀死线程的部分,因为我没有接触到算法的那部分——问题在之前。
#include "stdafx.h"
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;
mutex m;
condition_variable cv;
bool datax = 0, dataz = 0, zPrinted = 0;
void T1(const int& x, int& z)
{
do {
unique_lock<mutex> lk(m);
cv.wait(lk, [] {return (datax); });
if (datax) {
z = x * x;
datax = 0;
dataz = 1;
lk.unlock();
while (dataz)
cv.notify_one();
}
} while (1);
}
void T2(const int& z)
{
do {
unique_lock<mutex> lk(m);
cv.wait(lk, [] {return (dataz); });
if (dataz) {
cout << "z = " << z << endl;
dataz = 0;
zPrinted = 1;
lk.unlock();
while (zPrinted)
cv.notify_one();
}
} while (1);
}
int main()
{
int x, z;
char c;
thread threadT1(T1, cref(x), ref(z));
thread threadT2(T2, cref(z));
do {
unique_lock<mutex> lk(m);
cout << "Enter x: ";
cin >> x;
datax = 1;
lk.unlock();
while (datax) {
cv.notify_one();
}
cv.wait(lk, [] {return zPrinted; });
zPrinted = 0;
cout << "Continue? (y/n): ";
cin >> c;
} while (c == 'y');
return 0;
}
问题出在这里:
lk.unlock();
while (datax) {
cv.notify_one();
}
cv.wait(lk, [] {return zPrinted; }); // <-- waiting on unlocked mutex
zPrinted = 0;
您正在等待一个解锁的互斥体,这是未定义的行为see here under notes。
除了上面指出的等待解锁互斥体的问题:
cv.wait(lk, [] {return zPrinted; });
您有未重新加入的线程,并且是 运行 无限循环。这是一个带有模组的工作版本来解决这些问题:
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;
mutex m;
condition_variable cv;
bool datax = 0, dataz = 0, zPrinted = 0;
bool kill = 0;
void T1(const int& x, int& z)
{
do {
unique_lock<mutex> lk(m);
cv.wait(lk, [] {return (datax+kill); });
if (kill) return;
if (datax) {
z = x * x;
datax = 0;
dataz = 1;
lk.unlock();
while (dataz)
cv.notify_one();
}
} while (1);
}
void T2(const int& z)
{
do {
unique_lock<mutex> lk(m);
cv.wait(lk, [] {return (dataz+kill); });
if (kill) return;
if (dataz) {
cout << "z = " << z << endl;
dataz = 0;
zPrinted = 1;
lk.unlock();
while (zPrinted)
cv.notify_one();
}
} while (1);
}
int main()
{
int x, z;
char c;
thread threadT1(T1, cref(x), ref(z));
thread threadT2(T2, cref(z));
do {
{
unique_lock<mutex> lk(m);
cout << "Enter x: ";
cin >> x;
datax = 1;
lk.unlock();
while (datax)
cv.notify_one();
}
{
unique_lock<mutex> lk(m);
cv.wait(lk, [] {return zPrinted; });
lk.unlock();
}
zPrinted = 0;
cout << "Continue? (y/n): ";
cin >> c;
} while (c == 'y');
kill = 1;
cv.notify_all();
threadT1.join();
threadT2.join();
return 0;
}
如您所见,我引入了一个新变量 "kill",当设置为 1 时,会导致两个线程退出它们的无限循环,这样它们就可以连接起来。