最全面的教程 C++使用mutex锁(语言提供+linux+windowns三种平台锁的使用)

文章我详细介绍了锁的实现,分别是C++11提供mutex,lock_guard,unique_lock,windonws提供的 mutex和Linux下提供的,方便对比使用

1.使用C++标准库提供

基本操作

创建互斥锁:std::mutex mtx;

加锁:mtx.lock();

解锁:mtx.unlock();

自动管理锁定:使用 std::lock_guardstd::unique_lock 进行自动加锁和解锁。

以下示例展示了如何使用 std::mutex 来保护共享资源:

#include <iostream>
#include <thread>
#include <mutex>
#include <vector>

std::mutex mtx; // 互斥锁
int counter = 0; // 共享资源

void increment_counter() {
    for (int i = 0; i < 1000; ++i) {
        std::lock_guard<std::mutex> lock(mtx); // 自动加锁和解锁
        ++counter;
        // mtx.unlock() 会在 lock_guard 对象销毁时自动调用
    }
}

int main() {
    std::thread t1(increment_counter);
    std::thread t2(increment_counter);

    t1.join();
    t2.join();

    std::cout << "Final counter value: " << counter << std::endl;
    return 0;
}

代码解释

std::mutex mtx;:创建一个互斥锁 mtx,用于保护共享变量 counter

std::lock_guard<std::mutex> lock(mtx);std::lock_guard 是 RAII(Resource Acquisition Is Initialization)风格的锁定工具,构造时加锁,析构时解锁,保证即使发生异常也能正确解锁。

t1.join();t2.join();:等待两个线程执行完毕。

std::unique_lock

相比 std::lock_guardstd::unique_lock 提供了更灵活的锁管理,例如延迟加锁、显式解锁等。

代码示例

#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx;

void print_thread_id(int id) {
    std::unique_lock<std::mutex> lock(mtx); // 加锁
    std::cout << "Thread " << id << " is running\n";
    lock.unlock(); // 手动解锁
}

int main() {
    std::thread t1(print_thread_id, 1);
    std::thread t2(print_thread_id, 2);

    t1.join();
    t2.join();

    return 0;
}

代码解释

std::unique_lock<std::mutex> lock(mtx);:与 std::lock_guard 不同,std::unique_lock 可以手动解锁、重新加锁,甚至可以延迟加锁。

lock.unlock();:手动解锁。在需要手动管理锁的复杂场景中,std::unique_lock 更灵活。

C++17还提供了共享锁,感兴趣可以留言。

死锁预防

在多线程程序中,确保锁的获取顺序一致,以防止死锁。避免同时锁定多个互斥锁,或者使用 std::lock 来同时锁定多个 mutex

代码示例

#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx1, mtx2;

void thread1() {
    std::lock(mtx1, mtx2); // 同时锁定多个 mutex,避免死锁
    std::lock_guard<std::mutex> lock1(mtx1, std::adopt_lock);
    std::lock_guard<std::mutex> lock2(mtx2, std::adopt_lock);
    std::cout << "Thread 1 is running\n";
}

void thread2() {
    std::lock(mtx1, mtx2); // 同时锁定多个 mutex,避免死锁
    std::lock_guard<std::mutex> lock1(mtx1, std::adopt_lock);
    std::lock_guard<std::mutex> lock2(mtx2, std::adopt_lock);
    std::cout << "Thread 2 is running\n";
}

int main() {
    std::thread t1(thread1);
    std::thread t2(thread2);

    t1.join();
    t2.join();

    return 0;
}

总结

std::mutex 是 C++11 提供的标准同步机制,保证了线程间对共享资源的互斥访问。

std::lock_guardstd::unique_lock 是 RAII 风格的锁定工具,分别适用于简单和复杂的锁定需求。

死锁 可以通过一致的锁定顺序或使用 std::lock 来避免。

2.Linux 下的 Mutex

在 Linux 下,通常使用 POSIX 线程库(pthread)来实现互斥锁。pthread 提供了 pthread_mutex_t 结构和相关函数来管理互斥锁。

代码示例
#include <iostream>
#include <pthread.h>
#include <unistd.h>

using namespace std;

pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; // 初始化互斥锁

void* print_numbers(void* arg) {
    for (int i = 0; i < 5; ++i) {
        pthread_mutex_lock(&mtx); // 加锁
        cout << "Thread " << pthread_self() << ": " << i << endl;
        pthread_mutex_unlock(&mtx); // 解锁
        sleep(1); // 模拟其他操作
    }
    return nullptr;
}

int main() {
    pthread_t t1, t2;

    // 创建两个线程
    pthread_create(&t1, nullptr, print_numbers, nullptr);
    pthread_create(&t2, nullptr, print_numbers, nullptr);

    // 等待线程结束
    pthread_join(t1, nullptr);
    pthread_join(t2, nullptr);

    // 销毁互斥锁
    pthread_mutex_destroy(&mtx);

    return 0;
}
Linux 中的操作
  • 初始化互斥锁:使用 pthread_mutex_init()PTHREAD_MUTEX_INITIALIZER 来初始化。
  • 加锁:使用 pthread_mutex_lock()
  • 解锁:使用 pthread_mutex_unlock()
  • 销毁互斥锁:使用 pthread_mutex_destroy()

3.Windows 下的 Mutex

在 Windows 下,使用 Windows API 提供的同步原语。常用的有 CreateMutex()WaitForSingleObject(),它们可以实现互斥锁的功能。此外,Windows 还提供了轻量级的 CRITICAL_SECTION,这类似于互斥锁,但只在单个进程内使用,效率更高。

使用 Mutex 对象
#include <iostream>
#include <windows.h>

using namespace std;

HANDLE mtx; // 互斥锁句柄

DWORD WINAPI print_numbers(LPVOID arg) {
    for (int i = 0; i < 5; ++i) {
        WaitForSingleObject(mtx, INFINITE); // 加锁
        cout << "Thread " << GetCurrentThreadId() << ": " << i << endl;
        ReleaseMutex(mtx); // 解锁
        Sleep(1000); // 模拟其他操作
    }
    return 0;
}

int main() {
    // 创建互斥锁对象
    mtx = CreateMutex(nullptr, FALSE, nullptr);

    // 创建两个线程
    HANDLE t1 = CreateThread(nullptr, 0, print_numbers, nullptr, 0, nullptr);
    HANDLE t2 = CreateThread(nullptr, 0, print_numbers, nullptr, 0, nullptr);

    // 等待线程结束
    WaitForSingleObject(t1, INFINITE);
    WaitForSingleObject(t2, INFINITE);

    // 关闭线程句柄
    CloseHandle(t1);
    CloseHandle(t2);

    // 销毁互斥锁
    CloseHandle(mtx);

    return 0;
}
Windows 中的操作
  • 创建互斥锁:使用 CreateMutex()
  • 加锁:使用 WaitForSingleObject()
  • 解锁:使用 ReleaseMutex()
  • 销毁互斥锁:使用 CloseHandle()

4.Windows 下的 CRITICAL_SECTION

CRITICAL_SECTION 是 Windows 提供的轻量级锁,只能用于单个进程内的线程同步,但比 Mutex 更高效。

代码示例
#include <iostream>
#include <windows.h>

using namespace std;

CRITICAL_SECTION cs; // 临界区对象

DWORD WINAPI print_numbers(LPVOID arg) {
    for (int i = 0; i < 5; ++i) {
        EnterCriticalSection(&cs); // 加锁
        cout << "Thread " << GetCurrentThreadId() << ": " << i << endl;
        LeaveCriticalSection(&cs); // 解锁
        Sleep(1000); // 模拟其他操作
    }
    return 0;
}

int main() {
    // 初始化临界区对象
    InitializeCriticalSection(&cs);

    // 创建两个线程
    HANDLE t1 = CreateThread(nullptr, 0, print_numbers, nullptr, 0, nullptr);
    HANDLE t2 = CreateThread(nullptr, 0, print_numbers, nullptr, 0, nullptr);

    // 等待线程结束
    WaitForSingleObject(t1, INFINITE);
    WaitForSingleObject(t2, INFINITE);

    // 关闭线程句柄
    CloseHandle(t1);
    CloseHandle(t2);

    // 删除临界区对象
    DeleteCriticalSection(&cs);

    return 0;
}

总结

  • std::mutex 是 C++11 提供的标准同步机制,保证了线程间对共享资源的互斥访问。
  • std::lock_guardstd::unique_lock 是 RAII 风格的锁定工具,分别适用于简单和复杂的锁定需求。
  • Linux:使用 POSIX 线程库 (pthread) 实现 Mutex。操作包括初始化、加锁、解锁和销毁。
  • Windows:使用 CreateMutex()WaitForSingleObject() 实现 Mutex,或使用 CRITICAL_SECTION 进行更高效的同步。
  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值