线程之间的通信不起作用 - C++
Communication between threads not working - C++
我正在尝试写一个简单的例子来说明生产者和消费者这两个线程之间的经典通信。生产者锁定互斥锁,生成随机字符串消息并将它们推入队列并释放锁。然后消费者锁定互斥锁并在屏幕上打印该数据。出于某种原因,在 运行 代码之后我得到了一段时间的空白终端,然后程序终止而没有任何输出!这是我的代码:
#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);
}
这段代码不是很好。如果你在调试器中 运行 它,你很快就会找到它停止的原因,即 ....
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 个字节。从字符串中移出一些 "random location"。原始的 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与读取队列的变量不同
最终在我的测试中,消费者跟不上生产者,需要某种形式的节流和结束条件。
总的来说,您的同步方案很好。除此之外,代码有一个 运行 时间错误,使用 std::string
s 的一些意外后果和不必要的(并且可能误导 reader)调用:unlock()
在 std::unique_ptr
.
after running the code I get blank terminal for some times and then
program terminates without any outputs
由于将指向 null 的指针分配给 std::string
:
,它挂起并终止
string new_msg = NULL;
你可以see here,这将导致 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 对象 将在 mutex
销毁时释放 mutex
25=] 示波器按原样退出:
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
...
我正在尝试写一个简单的例子来说明生产者和消费者这两个线程之间的经典通信。生产者锁定互斥锁,生成随机字符串消息并将它们推入队列并释放锁。然后消费者锁定互斥锁并在屏幕上打印该数据。出于某种原因,在 运行 代码之后我得到了一段时间的空白终端,然后程序终止而没有任何输出!这是我的代码:
#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);
}
这段代码不是很好。如果你在调试器中 运行 它,你很快就会找到它停止的原因,即 ....
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 个字节。从字符串中移出一些 "random location"。原始的 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与读取队列的变量不同
最终在我的测试中,消费者跟不上生产者,需要某种形式的节流和结束条件。
总的来说,您的同步方案很好。除此之外,代码有一个 运行 时间错误,使用 std::string
s 的一些意外后果和不必要的(并且可能误导 reader)调用:unlock()
在 std::unique_ptr
.
after running the code I get blank terminal for some times and then program terminates without any outputs
由于将指向 null 的指针分配给 std::string
:
string new_msg = NULL;
你可以see here,这将导致 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 对象 将在 mutex
销毁时释放 mutex
25=] 示波器按原样退出:
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
...