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

时间:2018-09-18 06:07:34

标签: c++ multithreading mutex

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

#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);
}

2 个答案:

答案 0 :(得分:2)

总体而言,您将获得同步方案。除此之外,该代码存在一个运行时错误,使用std::string会产生一些意想不到的后果,并且在{{1}上对unlock()的不必要调用会导致: }。

  

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

由于将指向null的指针分配给std::unique_ptr ,它挂起并终止:

std::string

您可以see here,这将导致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();RAII对象,它将在std::unique_lock被销毁时释放mutex范围的退出原样:

while

输出:

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();
    }
}

答案 1 :(得分:1)

此代码的格式不正确。如果在调试器中运行它,您会很快找到它停止的原因,即....

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与读取队列的变量不同。

最后,在我的测试中,消费者跟不上生产者,并且需要某种形式的节流和终止条件。