首页 > 解决方案 > 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;
}

标签: c++multithreadinglockingmutexcondition-variable

解决方案


除了上面指出的等待解锁互斥锁的问题:

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 时,会导致两个线程退出它们的无限循环,以便它们可以被加入。


推荐阅读