[英]C++11 pass std::unique_lock<std::mutex> to lambda
[英]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_lock
或std::lock_guard
為成員變量時,會忽略范圍鎖定和鎖定。
我們的想法是在線程之間進行共享鎖定,但每個線程都會鎖定鎖保護的共享資源。 包裝器對象使其從函數返回安全且異常安全。
你首先要考慮你的共享資源。 在“工人”的背景下,我想象一些任務隊列。 然后,該任務隊列與某個鎖相關聯。 每個worker都使用scoped-wrapper鎖定該鎖,以便對任務進行排隊或將其出列。 只要工作線程的某個實例處於活動狀態,就沒有真正的理由保持鎖定鎖定,它應該在需要時將其鎖定。
出於多種原因這樣做並不是一個好主意。 第一個你已經用try-catch塊“處理”了:試圖鎖定同一個鎖的兩個線程導致異常。 如果您想要非阻塞鎖定嘗試,則應使用try_lock
。
第二個原因是當std::unique_lock
在鎖定持續時間范圍內進行堆棧分配時,那么當它被破壞時,它將為您解鎖資源。 這意味着它是異常安全的,如果workerThread.join()
拋出當前代碼,那么鎖將保持獲取狀態。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.