首页 > 编程语言 >C++之锁

C++之锁

时间:2023-07-08 11:23:32浏览次数:32  
标签:std 之锁 int C++ mutex shared include data

背景

在C++多线程编程中,锁是一种常用的同步原语,用于保护共享数据的访问。C++标准库提供了多种锁类型,适用于不同的使用场景。在这篇博客中,我们将介绍C++中的各种锁类型,比较它们的特点,并探讨不同锁在实际应用中的使用场景。

std::mutex

std::mutex是C++标准库中最基本的互斥锁类型,它提供了基本的锁定和解锁操作。std::mutex适用于保护简单的共享数据,如整数、指针等。

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

std::mutex mtx;
int shared_data = 0;

void increment() {
    mtx.lock();
    ++shared_data;
    mtx.unlock();
}

int main() {
    std::thread t1(increment);
    std::thread t2(increment);
    t1.join();
    t2.join();
    std::cout << "Shared data: " << shared_data << std::endl;
    return 0;
}

std::recursive_mutex

std::recursive_mutex是一种递归互斥锁,它允许同一个线程多次锁定同一个互斥锁。这种锁适用于需要在递归函数中保护共享数据的场景。

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

std::recursive_mutex rmtx;
int shared_data = 0;

void recursive_increment(int depth) {
    if (depth <= 0) return;

    rmtx.lock();
    ++shared_data;
    recursive_increment(depth - 1);
    rmtx.unlock();
}

int main() {
    std::thread t1(recursive_increment, 3);
    std::thread t2(recursive_increment, 3);
    t1.join();
    t2.join();
    std::cout << "Shared data: " << shared_data << std::endl;
    return 0;
}

std::timed_mutex

std::timed_mutex是一种带超时的互斥锁,它提供了尝试加锁一定时间的功能。这种锁适用于需要在超时后执行其他操作的场景。

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

std::timed_mutex tmtx;
int shared_data = 0;

void timed_increment() {
    if (tmtx.try_lock_for(std::chrono::seconds(1))) {
        ++shared_data;
        std::this_thread::sleep_for(std::chrono::seconds(2));
        tmtx.unlock();
    } else {
        std::cout << "Timeout, could not lock mutex." << std::endl;
    }
}

int main() {
    std::thread t1(timed_increment);
    std::thread t2(timed_increment);
    t1.join();
    t2.join();
    std::cout << "Shared data: " << shared_data << std::endl;
    return 0;
}

std::shared_mutex / std::shared_timed_mutex

std::shared_mutex和std::shared_timed_mutex是一种读写锁,它们允许多个线程同时读取共享数据,但在写入数据时只允许一个线程访问。这种锁适用于读操作远多于写操作的场景。

#include <iostream>
#include <thread>
#include <shared_mutex>
#include <vector>

std::shared_mutex smtx;
int shared_data = 0;

void read_data() {
    std::shared_lock<std::shared_mutex> lock(smtx);
    std::cout << "Read data: " << shared_data << std::endl;
}

void write_data(int value) {
    std::unique_lock<std::shared_mutex> lock(smtx);
    shared_data = value;
    std::cout << "Write data: " << shared_data << std::endl;
}

int main() {
std::vector<std::thread> readers;
for (int i = 0; i < 5; ++i) {
    readers.push_back(std::thread(read_data));
}

std::thread writer(write_data, 42);

for (auto& t : readers) {
    t.join();
}
writer.join();

return 0;
}

各种锁的比较与使用场景

  • std::mutex:基本的互斥锁,适用于简单共享数据的保护。
  • std::recursive_mutex:递归互斥锁,适用于需要在递归函数中保护共享数据的场景。
  • std::timed_mutex:带超时的互斥锁,适用于需要在超时后执行其他操作的场景。
  • std::shared_mutex / std::shared_timed_mutex:读写锁,适用于读操作远多于写操作的场景。

最后

总结一下,在这篇博客中,我们介绍了C++中的各种锁类型,比较了它们的特点,并探讨了不同锁在实际应用中的使用场景。通过合理地选择和使用锁,我们可以有效地保护共享数据,确保多线程程序的正确性和稳定性。在进行多线程编程时,我们需要了解各种锁的特点和适用场景,以便在不同场合选择合适的锁来保护共享数据。

标签:std,之锁,int,C++,mutex,shared,include,data
From: https://www.cnblogs.com/blizzard8204/p/17536940.html

相关文章

  • C++之future
    背景在C++多线程编程中,同步线程间的操作和结果通常是一个关键问题。C++11引入了std::future这一同步原语,用于表示异步操作的结果。本文将介绍C++中std::future的使用方法、优势以及与其他同步方法的对比。使用std::futurestd::future表示一个异步操作的结果,可以用于获取操作的......
  • C++之条件竞争
    背景在多线程编程中,线程间共享数据是一种常见的情况。然而,如果不加以处理,共享数据可能导致一些问题,如条件竞争。在这篇博客中,我们将介绍C++线程共享数据的问题,包括条件竞争的概念以及防止恶性条件竞争的方法。什么是条件竞争?条件竞争(RaceCondition)是指多个线程在访问和操作共......
  • C++之共享数据
    背景在C++多线程编程中,线程间共享数据是一种常见的情况。然而,如果不加以处理,共享数据可能导致一些问题,如条件竞争。本文将介绍C++中多线程共享数据的方式,包括各种方式的使用场景和比较。使用互斥锁(Mutex)互斥锁(Mutex)是一种同步原语,用于保护共享数据的访问。当一个线程访问共享数......
  • C++之死锁
    背景在多线程编程中,死锁是一个常见的问题,它会导致程序陷入无法继续执行的状态。在这篇博客中,我们将介绍C++中死锁的概念、产生原因以及解决办法。什么是死锁?死锁是指多个线程在等待对方释放资源,导致彼此都无法继续执行的情况。死锁通常发生在多个线程同时锁定多个互斥锁的情况......
  • C++之线程管控(一)
    背景多线程编程在实际应用中非常常见,它可以帮助我们提高程序性能,实现高效的任务调度。从C++11开始,C++语言已经提供了对多线程编程的原生支持。本文将详细介绍如何使用C++进行线程管控,包括发起线程、等待线程完成、异常处理以及在后台运行线程等内容。发起线程C++11提供了一个名......
  • C++之线程管控(二)
    背景随着多核处理器的普及,多线程编程已经成为软件开发中不可或缺的一部分。C++11标准为我们带来了线程库,让我们能够更方便地在C++中实现多线程编程。在这篇博客中,我们将介绍C++线程管控的基本概念和方法,包括向线程函数传递参数,移交线程归属权,运行时选择线程数量和识别线程。向线......
  • C++ Primer 学习笔记——第七章
    第七章类前言基本数据类型有时候并不能解决某些特定问题,而通过自定义的类就可以通过理解问题概念,使得程序更加容易编写、调试和修改。类的基本思想是数据抽象(dataabstraction)和封装(encapsulation)。数据抽象是一种依赖于接口(interface)和实现(implementation)分离的编程(以及设......
  • c++ 科幻版 沙漠神殿2
    #include<iostream>#include"minecraft.h"#include<string>usingnamespacestd;TxMinecraftmc;intx,y,z;boolcon;boollianjie(){ returncon=mc.ConnectMinecraft("mc.makeblock.net.cn","a9d44e758f6e4cf8b2da26241......
  • 请使用C++计算出2^2023与3^2023的和
    易知,这个和的数字是非常大的,大到longlong都装不下,这个时候如果使用longlong是无法进行运算的。欸!这会高精度算法(即大数运算)就开始发光发热了。以下是我看资料总结的一些歪瓜裂枣。对于一位高精度数字,用整数数组存储,数组每一个元素对应一位十进制数,由其下标顺序指明位序号......
  • c++沙漠神殿
    #include<iostream>#include"minecraft.h"#include<string>usingnamespacestd;TxMinecraftmc;intx=0,y=0,z=0;intmain(intargc,char**argv){boolcon=mc.ConnectMinecraft("zk.makeblock.net.cn","a9d44e758f6e4cf8b......