C++:使用互斥锁和条件变量控制线程执行顺序

C++: Control order of thread execution with mutex's and conditional variables

本文关键字:控制 变量 控制线 线程 顺序 执行 条件 C++      更新时间:2023-10-16

这个问题是这个问题的后续问题。我希望线程执行一些工作,并按顺序传递句柄给下一个线程。当尝试执行以下代码时,我得到

ConsoleApplication9.exe中0x0F7C1F5F (msvcp120 .dll)的未处理异常:0xC0000005:访问违反读取位置0x00000004.

    #include "stdafx.h"
    #include <iostream>
    #include <thread>
    #include <mutex>
    #include <chrono>
    #include <condition_variable> 
    std::mutex* m_pMutexs;
    std::condition_variable* m_pCVs;
    int m_pCurrentWorker;
    void func(int i)
    {
        int cvCurrentInd = i;
        std::mutex* pCurMutex = &m_pMutexs[cvCurrentInd];
        std::condition_variable* pCuCV = (std::condition_variable*)(m_pCurrentWorker + i*sizeof(std::condition_variable));
        std::unique_lock<std::mutex> lk(m_pMutexs[i]);
        while (i != m_pCurrentWorker)
        {
            pCuCV->wait(lk);
        }
        std::cout << "entered thread " << std::this_thread::get_id() << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(rand() % 10));
        std::cout << "leaving thread " << std::this_thread::get_id() << std::endl;
        m_pCurrentWorker++;
        lk.unlock();
        pCuCV->notify_one();
    }
    int _tmain(int argc, _TCHAR* argv[])
    {
        m_pMutexs = new std::mutex[3];
        m_pCVs = new std::condition_variable[3];
        m_pCurrentWorker = 0;
        srand((unsigned int)time(0));
        std::thread t1(func,0);
        std::thread t2(func,1);
        std::thread t3(func,2);
        t1.join();
        t2.join();
        t3.join();
        return 0;
    }

不知道你在做什么,但是

你要将整型转换为指针?

std::condition_variable* pCuCV = (std::condition_variable*)(m_pCurrentWorker + i*sizeof(std::condition_variable));

我认为你应该这样写:

std::condition_variable* pCuCV = &m_pCVs[i];

整个函数可以是这样的:

void func(int i)
{
    std::mutex* pCurMutex = &m_pMutexs[i];
    std::condition_variable* pCuCV = &m_pCVs[i];
    std::unique_lock<std::mutex> lk(m_pMutexs[i]);
    while (i != m_pCurrentWorker) {
        pCuCV->wait(lk);
    }
    std::cout << "entered thread " << std::this_thread::get_id() << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(rand() % 2));
    std::cout << "leaving thread " << std::this_thread::get_id() << std::endl;
    m_pCurrentWorker++;
    lk.unlock();
    if (m_pCurrentWorker > 2) {
        return;
    }
    pCuCV = &m_pCVs[m_pCurrentWorker];
    pCuCV->notify_one();
}

我做了一些进一步的研究,似乎原始问题的代码不是线程安全的