c++ - C++多线程中的锁和条件变量问题
问题描述
我正在尝试在 C++(Windows 10,Visual Studio Express)中实现一个简单的多线程示例。
我有计算 z = x * x 的线程 T1,其中 x 和 z 是全局变量。线程T2 显示 z。
我想使用锁和条件变量。
由于某种原因,在 T1 未阻塞时执行卡住了(在 cv.wait 之后,可能在 while 循环中 - 高 CPU 使用率)。但是当我在in main()之前添加一些代码(我尝试过)时,这不会发生cout << "x" << endl;
cv.notify_one();
。这很奇怪。
预先感谢您的帮助!
这是代码。我删除了我用来杀死线程的部分,因为我没有进入算法的那部分——问题是之前的。
#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;
}
解决方案
除了上面指出的等待解锁互斥锁的问题:
cv.wait(lk, [] {return zPrinted; });
您有未重新加入的线程并且正在运行无限循环。这是一个带有 mods 的工作版本来解决这些问题:
#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 时,会导致两个线程退出它们的无限循环,以便它们可以被加入。
推荐阅读
- typescript - 具有推断类型的函数参数在 return 中没有智能感知,而在函数体的其余部分有
- javascript - 我如何删除没有 id 或 somthings 的拥有标签...通过 jquery
- go - 无法使用书中的示例模拟死锁
- node.js - 使用 GET 定义相同的常量,但使用 POST 未定义 - express、mongo、react
- postgresql - Docker容器+postgresql接口依赖
- javascript - 如何使用纯 JavaScript 选择网页上的每个元素
- python - 创建一个带有 4 个类的烧瓶模型,其中包含一个 1:M 连接和一个涉及 User 类的 M:M 连接
- python - 在 Python 中如何实现交换变量?
- javascript - 我的快递模块有问题
- html - Bootstrap 4,CSS 问题 - 我的容器卡在导航栏上