线程之间的通信不起作用 - C++

Communication between threads not working - C++

本文关键字:C++ 不起作用 通信 之间 线程      更新时间:2023-10-16

我正在尝试编写一个简单的例子,说明生产者和消费者这两个线程之间的经典通信。创建者锁定互斥锁,生成随机字符串消息,并将它们推送到队列并释放锁。然后使用者锁定互斥锁并在屏幕上打印该数据。出于某种原因,运行代码后,我得到空白终端一段时间,然后程序终止而没有任何输出!这是我的代码:

#include <iostream>
#include <stdlib.h>
#include <thread>
#include <mutex>
#include <queue>
#include <random>
#include <string>
#include <cstdlib>
using namespace std;
static mutex mmutex;
static condition_variable mcond;
static queue <string> mqueue;
void consumer() {
while (true) {
unique_lock<mutex> lck{mmutex};
mcond.wait(lck);
string new_string = "producer has not produced yet ";
string m = "";
if (!mqueue.empty()) {
m = mqueue.front();
mqueue.pop();
string new_string = "producer produced " + m;
}   
cout << new_string << endl;
lck.unlock();
}
}
void producer() {
while (true) {
string new_msg = NULL;
unique_lock<mutex> lck{mmutex};
int random = rand() % 40 + 40;
new_msg = "New Random Char is "+static_cast <char> (random);
mqueue.push(new_msg);
mcond.notify_one();
}
}


int main() {
thread t1{ producer };
thread t2{ consumer };

t1.join();
t2.join();
cout << "exiting"<<endl;
system("PAUSE");
exit(0);
}

总的来说,你得到了很好的同步方案。除此之外,代码还有一个运行时错误,使用std::string的一些意外后果以及不必要(并且可能误导读者(调用:unlock()std::unique_ptr

运行代码后,我得到空白终端一段时间,然后 程序终止,没有任何输出

由于将指针分配给 null 到std::string,它挂起并终止:

string new_msg = NULL;

正如您在此处看到的,这将导致std::string实例尝试访问此地址零:(

其次,您无法通过将字符串文本char连接起来来获得所需的内容,如以下行所示:

string new_string = "producer produced " + m;

new_msg = "New Random Char is "+static_cast <char> (random);

下面是线程过程的一个工作版本,编写得稍好一些,您可以在其中看到各种有效的方法来初始化和分配给std::string以获取所需的内容。再次请注意,删除lck.unlock();,因为std::unique_lock是一个RAII对象,它将在while范围退出时将其销毁时释放mutex,如下所示:

void consumer() {
while (true) {
unique_lock<mutex> lck{ mmutex };
mcond.wait(lck);
string new_string;
if (!mqueue.empty()) {
string m = mqueue.front();
mqueue.pop();
new_string = string("producer produced ") + m;
}
else
{
new_string = "producer has not produced yet ";
}
cout << new_string << endl;
//lck.unlock(); // <--- Not the intended usage of `unique_lock`
}
}
void producer() {
while (true) {
string new_msg("New Random Char is ");
unique_lock<mutex> lck{ mmutex };
int random = rand() % 40 + 40;
new_msg += static_cast<char>(random);
mqueue.push(new_msg);
mcond.notify_one();
}
}

输出:

producer produced New Random Char is F
producer produced New Random Char is =
producer produced New Random Char is K
producer produced New Random Char is N
producer produced New Random Char is *
producer produced New Random Char is :
producer produced New Random Char is 3
producer produced New Random Char is O
producer produced New Random Char is @
producer produced New Random Char is E
producer produced New Random Char is I
...

这段代码的状态不是很好。 如果在调试器中运行它,您可以很快找到它停止的原因,即....

string new_msg = NULL;

这是一种访问冲突,其中读取 0 (NULL( 处的字节以获取字符串。

纠正:

string new_msg;  // default value is empty.

删除它后,需要进行一些必要的更改,以使代码更接近预期行为。

new_msg = "New Random Char is "+static_cast <char> (random);

这不起作用,因为它获取字符串的地址,并向其添加 40 到 80 个字节。 它从字符串中移动到某个"随机位置"。 原始的 C 兼容性在这里受到打击,而做(我相信(意图的正确方法是......

new_msg = string("New Random Char is ") +static_cast <char> (random);

当转换为std::string时,+ 现在表现为追加运算符。

终于在消费者...

string new_string = "producer produced " + m;

需要

new_string = "producer produced " + m;

否则,用于生成结果的变量new_string与读取队列的变量不同。

最后,在我的测试中,消费者没有跟上生产者的步伐,需要有某种形式的限制和最终条件。