C++锁机制

互斥锁

成员方法:lock(), try_lock(), unlock()

1
2
std::mutex mutex
std::shared_mutex mutex
1
2
3
4
5
6
7
8
9
myMutex.lock(); // 或者使用 std::lock_guard<std::mutex> guard(myMutex);
// 临界区代码
myMutex.unlock();
// 在 lock_guard 的情况下,不需要手动 unlock,它会在离开作用域时自动释放锁
// 尝试锁定两个互斥量
if (std::try_lock(lock1, lock2) == std::defer_lock) {
// 成功锁定两个互斥量,执行临界区代码
// ...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <thread>
#include <mutex>

// 定义互斥锁
std::mutex g_mutex;

// 临界区代码
void critical_section(int thread_id) {
// 加锁
g_mutex.lock();
// 访问共享资源
std::cout << "Thread " << thread_id << " enter critical section." << std::endl;
// 释放锁
std::this_thread::sleep_for(std::chrono::seconds(5));
g_mutex.unlock();
}

int main() {
// 创建两个线程
std::thread t1(critical_section, 1);
std::thread t2(critical_section, 2);
// 等待两个线程执行完成
t1.join();
t2.join();
return 0;
}

lock_guard

建议使用 lock_guard 替代直接使用 mutext.lock()mutext.unlock()lock_guard 会在构造方法里 mutext.lock(),析构方法里 mutext.unlock(),主要为了避免中途异常退出导致 mutext 没有 unlock,出了作用域后自动调用 lock_guard 的析构方法

unique_lock

lock_guard 只能在析构的时候解锁,不提供 unlock 接口,不够方便,unique_lock 提供 lockunlock 接口,更灵活,虽然 unique_locklock_guard 灵活很多,但是效率上差一点,内存占用多一点。

递归锁

C++ 中的递归互斥量是一种特殊的互斥量,它可以被同一个线程多次锁定,而不会发生死锁。递归互斥量的实现原理是,在锁定时维护一个锁定计数器,每次解锁时将计数器减一,只有当计数器为 0 时才会释放锁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <thread>
#include <mutex>

std::recursive_mutex mtx;

void foo(int n) {
mtx.lock();
std::cout << "Thread " << n << " locked the mutex." << std::endl;
if (n > 1) {
foo(n - 1);
}
std::cout << "Thread " << n << " unlocked the mutex." << std::endl;
mtx.unlock();
}

int main() {
std::thread t1(foo, 3);
std::thread t2(foo, 2);
t1.join();
t2.join();
return 0;
}

条件锁

成员方法:wait、wait_for、notify_one、notify_all

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>
#include <thread>
#include <chrono>
#include <queue>
#include <mutex>
#include <condition_variable>

std::queue<int> data_queue; // 数据队列
std::mutex data_mutex; // 互斥锁
std::condition_variable data_cond; // 条件变量

// 生产数据函数
void producer() {
for (int i = 1; i <= 10; ++i) {
// 生产数据
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::unique_lock<std::mutex> lock(data_mutex);
data_queue.push(i);
std::cout << "Producer thread: produce data " << i << std::endl;

// 唤醒消费线程
data_cond.notify_one();
}
}

// 消费数据函数
void consumer() {
while (true) {
// 等待数据
std::unique_lock<std::mutex> lock(data_mutex);
data_cond.wait(lock, [] { return !data_queue.empty(); });

// 消费数据
int data = data_queue.front();
data_queue.pop();
std::cout << "Consumer thread: consume data " << data << std::endl;

// 检查是否结束
if (data == 10) {
break;
}
}
}

int main() {
std::thread t1(producer);
std::thread t2(consumer);
t1.join();
t2.join();
return 0;
}

读写锁

成员方法:lock(), unlock(), lock_shared, unlock_shared

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
#include <shared_mutex>
#include <thread>

std::shared_mutex sharedMtx;
int sharedData = 0;

void readData() {
sharedMtx.lock_shared();
// 执行读取操作
std::cout << "Read shared data: " << sharedData << std::endl;
sharedMtx.unlock_shared();
}

void writeData() {
sharedMtx.lock();
// 执行写入操作
sharedData++;
std::cout << "Write shared data: " << sharedData << std::endl;
sharedMtx.unlock();
}

int main() {
std::thread readerThread1(readData);
std::thread readerThread2(readData);
std::thread writerThread(writeData);

readerThread1.join();
readerThread2.join();
writerThread.join();

return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <iostream>
#include <thread>
#include <chrono>
#include <shared_mutex>

std::shared_mutex rw_lock; // 读写锁
int shared_var = 0; // 共享变量

// 写线程函数
void writer() {
for (int i = 0; i < 10; ++i) {
// 独占写锁
std::unique_lock<std::shared_mutex> lock(rw_lock);

// 写共享变量
++shared_var;
std::cout << "Writer thread: write shared_var=" << shared_var << std::endl;

// 等待一段时间
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}

// 读线程函数
void reader(int id) {
for (int i = 0; i < 10; ++i) {
// 共享读锁
std::shared_lock<std::shared_mutex> lock(rw_lock);

// 读共享变量
int value = shared_var;
std::cout << "Reader thread " << id << ": read shared_var=" << value << std::endl;

// 等待一段时间
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}

int main() {
std::thread t1(writer);
std::thread t2(reader, 1);
std::thread t3(reader, 2);
std::thread t4(reader, 3);
t1.join();
t2.join();
t3.join();
t4.join();
return 0;
}