C++ 锁的使用

1. std 标准库中的锁

STD 标准中的锁。

# 声明
std::mutex handle_mutex;
 
# 使用1 互斥锁
std::lock_guard<std::mutex> lock(handle_mutex);
 
# 使用2 独占锁
std::unique_lock<std::mutex> lock(handle_mutex);
 
# 使用3 允许同一个线程多次锁定同一把锁。对于递归函数可能需要在同一线程中多次获取锁的情况很有用
std::unique_lock<std::recursive_mutex> lock(handle_mutex);
 

1.1. 共享锁

  • 多个线程可以同时获得共享锁,可以并发的读取共享资源
  • 共享锁使用 std::shared_lock 获取
#include <shared_mutex>
 
std::shared_mutex mySharedMutex;
 
void readOperation() {
    std::shared_lock<std::shared_mutex> lock(mySharedMutex);
    // 读取共享资源的代码
}

1.2. 独占锁

  • 只允许一个线程可以获得独占锁,能够独占资源
  • 独占锁使用 std::unqiue_lock 获取
#include <shared_mutex>
 
std::shared_mutex mySharedMutex;
 
void writeOperation() {
    std::unique_lock<std::shared_mutex> lock(mySharedMutex);
    // 修改共享资源的代码
}

2. Demo

如下所示

  • 使用 std::shared_lock 进行读取操作,使用 std::unique_lock 进行写入操作。
  • 避免在写入操作中使用共享锁,以免破坏写者的互斥性
#include <iostream>
#include <shared_mutex>
#include <vector>
#include <thread>
 
int sharedData=0;
std::shared_mutex mySharedMutex;
 
void readOperation(int id) {
    //std::shared_lock<std::shared_mutex> lock(mySharedMutex);
    mySharedMutex.lock_shared();//手动控制
    // 读取共享资源的代码
    std::cout << "Reader " << id << " reading data: " << sharedData << std::endl;
    mySharedMutex.unlock_shared();//手动控制
}
 
void writeOperation(int id) {
    //std::unique_lock<std::shared_mutex> lock(mySharedMutex);
    mySharedMutex.lock();//手动控制
    
    // 修改共享资源的代码
    sharedData=id;
    std::cout << "Writer " << id << " writing data." << std::endl;
    mySharedMutex.unlock();//手动控制
}
 
int main() {
    std::vector<std::thread> readers;
    std::vector<std::thread> writers;
 
    for (int i = 0; i < 5; ++i) {
        readers.emplace_back(readOperation, i);
        writers.emplace_back(writeOperation, i);
    }
 
    for (auto& reader : readers) {
        reader.join();
    }
 
    for (auto& writer : writers) {
        writer.join();
    }
 
    return 0;
}
 

使用 Windows 的 CComAutoCriticalSection

class CAutoCriticalSection
{
public:
	CAutoCriticalSection(CComAutoCriticalSection* lpSect) :
		m_pCS(lpSect)
	{
		m_pCS->Lock();
	}
 
	~CAutoCriticalSection()
	{
		m_pCS->Unlock();
	}
 
protected:
private:
	CComAutoCriticalSection* m_pCS;
};

如何使用

# 声明
CComAutoCriticalSection g_csLoginLock;
 
# 定义
CAutoCriticalSection csLock(&g_csLoginLock);