簡體   English   中英

在C ++ 11中,使用std :: unique_lock <std :: mutex>作為類成員是否明智(甚至安全)?如果是的話,有沒有指導方針?

[英]In C++11, is it wise (or even safe) to use std::unique_lock<std::mutex> as a class member? If so, are there any guidelines?

使用std :: unique_lock作為類成員是否明智(甚至安全)? 如果是的話,有沒有指導方針?

我在使用std :: unique_lock時的想法是確保在拋出異常的情況下解鎖互斥鎖。

以下代碼給出了我當前如何使用unique_lock的示例。 在項目增長太多之前,我想知道我是否走錯了方向。

#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <unistd.h>


class WorkerClass {
private:
    std::thread workerThread;
    bool workerThreadRunning;
    int workerThreadInterval;

    int sharedResource;

    std::mutex mutex;
    std::unique_lock<std::mutex> workerMutex;

public:
    WorkerClass() {
        workerThreadRunning = false;
        workerThreadInterval = 2;

        sharedResource = 0;

        workerMutex = std::unique_lock<std::mutex>(mutex);

        unlockMutex();
    }


    ~WorkerClass() {
        stopWork();
    }


    void startWork() {
        workerThreadRunning = true;
        workerThread = std::thread(&WorkerClass::workerThreadMethod,
                                   this);
    }


    void stopWork() {
        lockMutex();
        if (workerThreadRunning) {
            workerThreadRunning = false;
            unlockMutex();
            workerThread.join();
        }else {
            unlockMutex();
        }
    }


    void lockMutex() {
        try {
            workerMutex.lock();
        }catch (std::system_error &error) {
            std::cout << "Already locked" << std::endl;
        }
    }


    void unlockMutex() {
        try {
            workerMutex.unlock();
        }catch (std::system_error &error) {
            std::cout << "Already unlocked" << std::endl;
        }
    }

    int getSharedResource() {
        int result;
        lockMutex();
        result = sharedResource;
        unlockMutex();
        return result;
    }


    void workerThreadMethod() {
        bool isRunning = true;

        while (isRunning) {
            lockMutex();
            sharedResource++;
            std::cout << "WorkerThread:  sharedResource = "
                      << sharedResource << std::endl;
            isRunning = workerThreadRunning;
            unlockMutex();

            sleep(workerThreadInterval);
        }
    }
};



int main(int argc, char *argv[]) {
    int sharedResource;
    WorkerClass *worker = new WorkerClass();

    std::cout << "ThisThread: Starting work..." << std::endl;
    worker->startWork();

    for (int i = 0; i < 10; i++) {
        sleep(1);

        sharedResource = worker->getSharedResource();
        std::cout << "ThisThread: sharedResource = "
                  << sharedResource << std::endl;
    }

    worker->stopWork();

    std::cout << "Done..." << std::endl;

    return 0;
}

這實際上非常糟糕。 std::unique_lockstd::lock_guard為成員變量時,會忽略范圍鎖定和鎖定。

我們的想法是在線程之間進行共享鎖定,但每個線程都會鎖定鎖保護的共享資源。 包裝器對象使其從函數返回安全且異常安全。

你首先要考慮你的共享資源。 在“工人”的背景下,我想象一些任務隊列。 然后,該任務隊列與某個鎖相關聯。 每個worker都使用scoped-wrapper鎖定該鎖,以便對任務進行排隊或將其出列。 只要工作線程的某個實例處於活動狀態,就沒有真正的理由保持鎖定鎖定,它應該在需要時將其鎖定。

出於多種原因這樣做並不是一個好主意。 第一個你已經用try-catch塊“處理”了:試圖鎖定同一個鎖的兩個線程導致異常。 如果您想要非阻塞鎖定嘗試,則應使用try_lock

第二個原因是當std::unique_lock在鎖定持續時間范圍內進行堆棧分配時,那么當它被破壞時,它將為您解鎖資源。 這意味着它是異常安全的,如果workerThread.join()拋出當前代碼,那么鎖將保持獲取狀態。

暫無
暫無

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

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