C++线程中几类锁的详解

C++线程中几类锁的详解

前言

在多线程编程中,锁是一种重要的同步机制,可以保证多个线程在访问共享资源时的安全性。C++提供了多种类型的锁,本篇文章将对常用的几种锁进行详解。

互斥锁(mutex)

互斥锁是最常用的一种锁,它保证同一时刻只有一个线程可以访问共享资源。当一个线程获得锁时,其他线程将一直等待直到拥有锁的线程释放锁为止。

创建互斥锁

C++标准库提供了std::mutex类实现互斥锁,创建一个互斥锁的方法如下:

std::mutex mutexObj;

加锁和解锁

互斥锁的加锁和解锁操作分别使用std::mutex类的lock()unlock()方法实现:

mutexObj.lock();
// 临界区代码
mutexObj.unlock();

互斥锁示例

下面是一个使用互斥锁保护共享资源的示例,其中共享资源为一个计数器,多个线程分别对计数器进行加一:

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

std::mutex mutexObj;
int count = 0;

void increaseCount()
{
    mutexObj.lock();

    for (int i=0; i<1000; i++) {
        count++;
    }

    mutexObj.unlock();
}

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

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

    std::cout << "count:" << count << std::endl;

    return 0;
}

在上面的示例中,通过互斥锁的加锁和解锁操作保证了count变量的安全性。如果不使用锁,那么多个线程同时访问count变量将会引发数据竞争问题。

递归锁(recursive mutex)

递归锁是一种互斥锁的变体,它允许同一线程多次获得锁而不会引起死锁。当一个线程对已经拥有的锁再次加锁时,递归锁会记录加锁次数,并在解锁时相应的解锁次数。

创建递归锁

C++标准库提供了std::recursive_mutex类实现递归锁,创建一个递归锁的方法如下:

std::recursive_mutex recursiveMutexObj;

加锁和解锁

递归锁的加锁和解锁操作分别使用std::recursive_mutex类的lock()unlock()方法实现。

递归锁示例

下面是一个使用递归锁保护共享资源的示例,其中共享资源为一个计数器,一个线程递归调用函数对计数器进行加一:

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

std::recursive_mutex recursiveMutexObj;
int count = 0;

void increaseCount()
{
    recursiveMutexObj.lock();
    count++;

    if (count < 1000) {
        increaseCount();
    }

    recursiveMutexObj.unlock();
}

int main()
{
    std::thread t1(increaseCount);
    t1.join();

    std::cout << "count:" << count << std::endl;

    return 0;
}

在上面的示例中,通过递归锁的加锁和解锁操作保证了count变量的安全性。虽然increaseCount()方法递归调用了多次,但是由于使用了递归锁,所以不会引起死锁或者其他线程对共享资源的竞争问题。

读写锁(read-write lock)

读写锁是一种特殊的锁,对于共享资源可以允许多个线程同时进行读访问,但是在进行写访问时需要互斥。读写锁可以提高读取操作的并发性,提高程序性能。

创建读写锁

C++标准库提供了std::shared_timed_mutex类实现读写锁,创建一个读写锁的方法如下:

std::shared_timed_mutex rwMutexObj;

读操作

对于读操作,可以使用std::shared_timed_mutex类的lock_shared()方法进行加锁,使用unlock_shared()方法进行解锁:

rwMutexObj.lock_shared();
// 共享资源读取操作
rwMutexObj.unlock_shared();

当多个线程对共享资源进行读操作时,可以用读写锁来提高并发性,示例如下:

读写锁示例

下面是一个使用读写锁保护共享资源的示例,其中共享资源为一个计数器,多个线程可以同时对计数器进行读取,但是对计数器进行写操作时需要互斥:

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

std::shared_timed_mutex rwMutexObj;
int count = 0;

void increaseCount()
{
    rwMutexObj.lock();
    count++;
    rwMutexObj.unlock();
}

void printCount()
{
    rwMutexObj.lock_shared();
    std::cout << "count:" << count << std::endl;
    rwMutexObj.unlock_shared();
}

int main()
{
    std::thread t1(increaseCount);
    std::thread t2(printCount);

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

    return 0;
}

在上面的示例中,通过读写锁的读和写操作,保证了count变量的安全性。由于多个线程可以同时对count变量进行读取,所以使用读写锁可以提高程序的并发性。

总结

本篇文章介绍了C++中常用的锁类型,包括互斥锁、递归锁和读写锁。通过适当的锁机制可以保证多线程访问共享资源的安全性,提高程序的并发性。在实际应用中应根据具体情况选择合适的锁机制,以达到最优的性能和安全性。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++线程中几类锁的详解 - Python技术站

(0)
上一篇 2023年5月22日
下一篇 2023年5月22日

相关文章

  • C语言通讯录管理系统完整代码

    C语言通讯录管理系统完整代码攻略 概述 本文将介绍C语言实现的通讯录管理系统的完整代码,并且对代码进行详细讲解说明。该代码实现的功能包括通讯录的增加、删除、修改、查询和展示等。 代码说明 代码结构 该代码主要分为两个文件,一个是 main.c,另一个是 contacts.h。其中 main.c 中包含了程序的入口 main 函数以及 contacts.h 的…

    C 2023年5月23日
    00
  • 用C语言实现简单的计算器功能

    创建计算器的布局 首先,我们需要创建一个简单的图形用户界面(GUI),以便用户可以愉快地使用我们的计算器。这里我们将使用C语言中的一个GUI库——GTK。 示例代码: #include <gtk/gtk.h> int main(int argc, char *argv[]) { //初始化 gtk_init(&argc, &arg…

    C 2023年5月23日
    00
  • C++实现闹钟程序的方法

    下面我来详细讲解一下 C++ 实现闹钟程序的方法。 一、实现思路 要实现闹钟程序,就需要先了解一下闹钟程序的基本功能:1)设置闹钟时间;2)定时器到时后发出提示音;3)停止提示音。根据这些功能,我们可以分解出以下几个步骤: 读取用户设置的闹钟时间; 判断当前时间是否等于闹钟时间,如果不等待,则继续等待; 定时器到时后,播放提示音; 用户选择关闭提示音或延迟提…

    C 2023年5月23日
    00
  • CrashRpt使用案例详解

    CrashRpt使用案例详解 简介 CrashRpt是一款用于记录和上报应用程序崩溃信息的库。它能够捕捉应用程序崩溃时的调用栈、CPU状态、内存信息等重要数据,并将这些信息打包成压缩文件并保存到本地硬盘,同时也可以将这些信息发送到云端。CrashRpt库适用于Windows操作系统,支持C++和一些其他语言,如C#、Python等。 安装 下载CrashRp…

    C 2023年5月23日
    00
  • c++ 队列相关知识总结

    C++ 队列相关知识总结 队列是一种线性数据结构,它只允许在队列的一端进行插入(入队)操作,在另一端进行删除(出队)操作,并且遵循先进先出(FIFO)的原则。在 C++ 中,队列一般通过 queue 容器来实现。 queue 容器的使用 queue 容器是一个模板类,需要包含头文件 <queue>,定义方式如下: queue<int>…

    C 2023年5月23日
    00
  • C++如何判断一个数字是否为质数

    下面是C++判断一个数字是否为质数的完整攻略,包含两条示例说明。 什么是质数 在数论中,质数是指除了 1 和本身之外,不能被其它正整数整除的数。比如,2、3、5、7、11、13等是质数,而4、6、8、9等不是质数。 C++中判断一个数字是否为质数 C++中判断一个数字是否为质数的方法一般是通过判断这个数是否能被除了1和它本身之外的其它数整除。这种判断方法比较…

    C 2023年5月23日
    00
  • Linux下C语言的几道经典面试题小结(分享)

    Linux下C语言的几道经典面试题小结(分享) 介绍 本文是对Linux下C语言的几道经典面试题进行的总结与分享。在C语言面试中,几道经典的问题一般都是用来测试面试者的基础知识和实际操作能力。在此处,将讨论面试中可能出现的几道经典问题,并提供相应答案和解释。本文将涵盖以下几个部分: 基本数据类型 数组和字符串 指针和内存 函数和指针 基本数据类型 问题1:s…

    C 2023年5月23日
    00
  • Linux中使用VS Code编译调试C++项目详解

    下面我将详细讲解如何在Linux中使用VS Code编译调试C++项目。 准备工作 安装VS Code 首先,我们需要安装一个文本编辑器,这里我们选择VS Code。可以到官网下载 Visual Studio Code。 下载完成后,解压安装文件并将其保存在可执行路径中(例如/usr/local/bin),使其能够在终端中运行。 安装C++编译器 接下来,我…

    C 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部