C++多线程编程中的锁详解

在现代软件开发中,多线程编程是提升应用程序性能和响应能力的重要手段。然而,多线程编程也带来了数据竞争和死锁等复杂问题。为了确保线程间的同步和共享数据的一致性,C++标准库提供了多种锁机制。

1. std::mutex

std::mutex是最基础的互斥锁,用于保护共享数据,防止多个线程同时访问该数据。

cpp 复制代码
#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx;

void print_thread_id(int id) {
    mtx.lock();
    std::cout << "Thread " << id << std::endl;
    mtx.unlock();
}

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

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

    return 0;
}

在上述代码中,mtx.lock()mtx.unlock()分别用于加锁和解锁,确保同一时刻只有一个线程可以访问临界区(std::cout操作)。

2. std::recursive_mutex

std::recursive_mutex允许同一线程多次获得同一锁,而不会导致死锁。适用于递归调用中需要加锁的场景。

cpp 复制代码
#include <iostream>
#include <thread>
#include <mutex>

std::recursive_mutex rec_mtx;

void recursive_function(int count) {
    if (count <= 0) return;
    rec_mtx.lock();
    std::cout << "Count: " << count << std::endl;
    recursive_function(count - 1);
    rec_mtx.unlock();
}

int main() {
    std::thread t(recursive_function, 5);
    t.join();

    return 0;
}

3. std::timed_mutex

std::timed_mutex支持尝试在一定时间内获取锁。这在避免死锁和提高程序响应性方面很有用。

cpp 复制代码
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>

std::timed_mutex tmtx;

void try_lock_for_example() {
    if (tmtx.try_lock_for(std::chrono::seconds(1))) {
        std::cout << "Lock acquired" << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(2));
        tmtx.unlock();
    } else {
        std::cout << "Failed to acquire lock" << std::endl;
    }
}

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

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

    return 0;
}

4. std::recursive_timed_mutex

std::recursive_timed_mutex结合了std::recursive_mutexstd::timed_mutex的特性

cpp 复制代码
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>

std::recursive_timed_mutex rtmtx;

void recursive_timed_function(int count) {
    if (count <= 0) return;
    if (rtmtx.try_lock_for(std::chrono::seconds(1))) {
        std::cout << "Count: " << count << std::endl;
        recursive_timed_function(count - 1);
        rtmtx.unlock();
    } else {
        std::cout << "Failed to acquire lock" << std::endl;
    }
}

int main() {
    std::thread t(recursive_timed_function, 5);
    t.join();

    return 0;
}

5. std::shared_mutex(C++17引入)

std::shared_mutex允许多个线程同时读取共享数据,但只允许一个线程写入数据。这种机制适用于读多写少的场景。

cpp 复制代码
#include <iostream>
#include <thread>
#include <shared_mutex>

std::shared_mutex smtx;

void read_function() {
    smtx.lock_shared();
    std::cout << "Reading data" << std::endl;
    smtx.unlock_shared();
}

void write_function() {
    smtx.lock();
    std::cout << "Writing data" << std::endl;
    smtx.unlock();
}

int main() {
    std::thread t1(read_function);
    std::thread t2(read_function);
    std::thread t3(write_function);

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

    return 0;
}

6. std::shared_timed_mutex(C++14引入)

std::shared_timed_mutex结合了std::shared_mutexstd::timed_mutex的特性。

cpp 复制代码
#include <iostream>
#include <thread>
#include <shared_mutex>
#include <chrono>

std::shared_timed_mutex stmtx;

void shared_timed_read_function() {
    if (stmtx.try_lock_shared_for(std::chrono::seconds(1))) {
        std::cout << "Reading data" << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(2));
        stmtx.unlock_shared();
    } else {
        std::cout << "Failed to acquire shared lock" << std::endl;
    }
}

void shared_timed_write_function() {
    if (stmtx.try_lock_for(std::chrono::seconds(1))) {
        std::cout << "Writing data" << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(2));
        stmtx.unlock();
    } else {
        std::cout << "Failed to acquire exclusive lock" << std::endl;
    }
}

int main() {
    std::thread t1(shared_timed_read_function);
    std::thread t2(shared_timed_read_function);
    std::thread t3(shared_timed_write_function);

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

    return 0;
}

7. std::lock_guard

std::lock_guard提供一种异常安全的方式来管理锁的生命周期,通常用于自动解锁。

cpp 复制代码
#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx;

void lock_guard_example() {
    std::lock_guard<std::mutex> lock(mtx);
    std::cout << "Lock acquired using lock_guard" << std::endl;
    // mtx is automatically unlocked when lock goes out of scope
}

int main() {
    std::thread t(lock_guard_example);
    t.join();

    return 0;
}

8. std::unique_lock

std::unique_lockstd::lock_guard更加灵活,支持延迟加锁、解锁和重新加锁。

cpp 复制代码
#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx;

void unique_lock_example() {
    std::unique_lock<std::mutex> lock(mtx);
    std::cout << "Lock acquired using unique_lock" << std::endl;
    lock.unlock();
    std::cout << "Lock released" << std::endl;
    lock.lock();
    std::cout << "Lock reacquired" << std::endl;
}

int main() {
    std::thread t(unique_lock_example);
    t.join();

    return 0;
}

9. std::shared_lock(C++17引入)

std::shared_lock用于管理共享互斥量(std::shared_mutexstd::shared_timed_mutex),提供了一种简单的方式来处理读锁。

cpp 复制代码
#include <iostream>
#include <thread>
#include <shared_mutex>

std::shared_mutex smtx;

void shared_lock_example() {
    std::shared_lock<std::shared_mutex> lock(smtx);
    std::cout << "Shared lock acquired" << std::endl;
}

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

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

    return 0;
}

结论

C++标准库提供了多种锁机制,帮助开发者在多线程环境中确保数据的一致性和线程的同步。根据具体的应用场景选择合适的锁,可以有效地避免数据竞争和死锁问题,从而编写出高效、安全的多线程程序。

相关推荐
wqfhenanxc22 分钟前
Mixing C++ and Rust for Fun and Profit 阅读笔记
c++·笔记·rust
R-G-B25 分钟前
【MFC】 VS2022打开低版本的MFC,双击.rc文件,DIalog加载失败,页面弹窗fatal error RC***:cannot open*****
c++·mfc·vs打开较早版本mfc·双击.rc文件·dialog加载失败·fatal error rc·cannot open
敲上瘾27 分钟前
基于Tcp协议的应用层协议定制
linux·运维·服务器·网络·c++·网络协议·tcp/ip
莹莹学编程—成长记1 小时前
string的模拟实现
服务器·c++·算法
喵先生!4 小时前
C++中的vector和list的区别与适用场景
开发语言·c++
xMathematics5 小时前
计算机图形学实践:结合Qt和OpenGL实现绘制彩色三角形
开发语言·c++·qt·计算机图形学·cmake·opengl
yuanManGan7 小时前
C++入门小馆: 深入了解STLlist
开发语言·c++
梁下轻语的秋缘7 小时前
每日c/c++题 备战蓝桥杯(P1049 [NOIP 2001 普及组] 装箱问题)
c语言·c++·学习·蓝桥杯
逐光沧海8 小时前
STL常用算法——C++
开发语言·c++
wuqingshun3141598 小时前
蓝桥杯 5. 交换瓶子
数据结构·c++·算法·职场和发展·蓝桥杯