簡體   English   中英

std :: thread在無限循環后的隨機時間后鎖定

[英]std::thread locks after a random time in an endless loop

我試圖為我的主應用程序實現3個其他線程,這些線程執行非共享操作。

起初,我認為它可以正常工作,因為如果我取消注釋WorkerThread函數中的最后一個printf調用,則在經過一段隨機時間后,它不會鎖定在WaitThread()上。 如果沒有printf,有時它需要花費幾秒鍾的時間才能鎖定在mWaitCond.Wait()函數上,有時甚至在啟動之后。 printf似乎可以解決線程的計時問題。

該應用程序不會崩潰,只是該應用程序的CPU使用率達到了0%(以及每個線程的使用率),並且它沒有響應。 在Visual Studio調試器中暫停顯示在WaitThread()函數中的while(mWakeUp)mWaitCondition.Wait()行作為當前位置。 它還顯示mWakeUp對於所有線程都是false,因此它不應停留在while循環中。

我在設計背后的想法:

  1. 在進入主循環之前調用SetupThreads()
  2. 在無限循環內,WorkerInit()被調用以喚醒線程
  3. 在我訪問3個線程的數據之前,調用WorkerWait()等待它們完成
  4. 在WorkerThread函數內部(由每個線程調用),即時鎖定互斥鎖並等待線程喚醒或停止
  5. 處理完數據后,wakeUp設置為false,並且condition_variable通知

難道是waitthread一個接一個地等待線程,並等待讓我們說索引0的線程,索引2的線程繼續運行?

    static const ui32 NumContexts = 3;

    // array of pointers to threads
    std::thread* mThreadHandles[NumContexts];

    // wakup
    std::atomic<bool> mWakeUp[NumContexts];
    std::mutex mWakeMutex[NumContexts];
    std::condition_variable mWakeCondition[NumContexts];

    // wait for thread to finish task
    std::mutex mWaitMutex[NumContexts];
    std::condition_variable mWaitCondition[NumContexts];

    // stop signal
    std::atomic<bool> mStop[NumContexts];

    void Framework::SetupThreading()
    {
        // create and start threads
        for (int i = 0; i < NumContexts; i++)
        {
            this->mWakeUp[i] = false;
            this->mStop[i] = false;
            this->mThreadHandles[i] = new  std::thread(&Framework::WorkerThread, this, reinterpret_cast<void*>(i));
        }
    }

    //---------------------------------------------
    void Framework::WakeUpThread(int i)
    {
        {
            //auto lock = std::unique_lock<std::mutex>(this->mWakeMutex[i]);
            std::lock_guard<std::mutex> lock(this->mWakeMutex[i]);
            //printf("Waking up thread %i \n", i);

            this->mWakeUp[i] = true;
        }
        this->mWakeCondition[i].notify_one();
    }

    // THIS FUNCTION LOCKS
    //---------------------------------------------
    void Framework::WaitThread(int i)
    {
        auto lock = std::unique_lock<std::mutex>(this->mWaitMutex[i]);
        //printf("Waiting for thread %i to finish \n", i);

        while (this->mWakeUp[i])
            this->mWaitCondition[i].wait(lock);

        //printf("Thread %i finished! \n", i);
    }

    //---------------------------------------------
    void Framework::StopThread(int i)
    {
        auto lock = std::unique_lock<std::mutex>(this->mWakeMutex[i]);
        printf("Sending stop signal for thread %i \n", i);
        this->mStop[i] = true;
        this->mWakeCondition[i].notify_one();
    }

    //---------------------------------------------
    void Framework::JoinThread(int i)
    {
        printf("Waiting for join of thread %i \n", i);
        this->mThreadHandles[i]->join();
        printf("Thread %i joined! \n", i);
    }

    // THESE ARE CALLED IN THE MAIN LOOP
    //---------------------------------------------
    void Framework::WorkerInit()
    {
        for (int i = 0; i < NumContexts; i++)
        {
            this->WakeUpThread(i);
        }
    }

    void Framework::WorkerWait()
    {
        for (int i = 0; i < NumContexts; i++)
        {
            this->WaitThread(i);
        }
    }

    // THE FUNCTION CALLED BY THE THREADS
    //---------------------------------------------
    void Framework::WorkerThread(LPVOID workerIndex)
    {
        int threadIndex = reinterpret_cast<int>(workerIndex);
        while (threadIndex < NumContexts && threadIndex >= 0)
        {
            {
                auto lock = std::unique_lock<std::mutex>(this->mWakeMutex[threadIndex]);
                //printf("thread %i: waiting for wakeup or stop signal...\n", threadIndex);

                // not stopped nor woken up? continue to wait
                while (this->mWakeUp[threadIndex] == false && this->mStop[threadIndex] == false)
                {
                    this->mWakeCondition[threadIndex].wait(lock);
                }

                // stop signal sent?
                if (this->mStop[threadIndex])
                {
                    //printf("thread %i: got stop signal!\n", threadIndex);
                    return;
                }
                //printf("thread %i: got wakeup signal!\n", threadIndex);

                // lock unlocks here (lock destructor)
            }

            //  printf("thread %i: running the task...\n", threadIndex);

             // RUN CODE HERE

                //printf("thread %i finished! Sending signal!...\n", threadIndex);

                // m_wakeup is atomic so there is no concurrency issue with wait()
                this->mWakeUp[threadIndex] = false;
                this->mWaitCondition[threadIndex].notify_all();


        }
    }

如果線程的CPU使用率為零,則它不會在while循環中旋轉,而是在wait()上阻塞。 在wait()解除阻塞之前,不會測試循環條件。

檢查調試器來驗證調用堆棧,該停止位置可能只是在你的源代碼指示返回位置,而隨后他當前的位置。

還要檢查WorkerThread實例的狀態-它們是否正在運行並調用notify_all() 您的調試器線程知道嗎?

我不確定我是否了解您的設計或意圖,但從表面上看,這似乎有些復雜,並且已經陷入僵局。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM