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

相关推荐
casual~1 小时前
第?个质数(埃氏筛算法)
数据结构·c++·算法
Elnaij1 小时前
从C++开始的编程生活(20)——AVL树
开发语言·c++
hanbr1 小时前
【C++ STL核心】vector:最常用的动态数组容器(第九天核心)
开发语言·c++
仰泳的熊猫2 小时前
题目2308:蓝桥杯2019年第十届省赛真题-旋转
数据结构·c++·算法·蓝桥杯
lzksword3 小时前
C++ Builder XE OpenDialog1打开多文件并显示xls与xlsx二种格式文件
java·前端·c++
niceffking3 小时前
C++内部类的ISO约定和语法细节
开发语言·c++
艾莉丝努力练剑4 小时前
【脉脉】AI创作者崛起:掌握核心工具,在AMA互动中共同成长
运维·服务器·c++·人工智能·安全·企业·脉脉
码界奇点4 小时前
基于ASP.NET Core的内容管理系统设计与实现
c++·后端·车载系统·毕业设计·asp.net·源代码管理
2401_883035464 小时前
C++20概念(Concepts)入门指南
开发语言·c++·算法
91刘仁德5 小时前
C++ 内存管理
android·c语言·数据结构·c++·经验分享·笔记·算法