iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++线程中几类锁的详解
  • 275
分享到

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

2024-04-02 19:04:59 275人浏览 泡泡鱼
摘要

目录c++线程中的几类锁互斥锁条件锁自旋锁读写锁参考博客总结C++线程中的几类锁 多线程中的锁主要有五类:互斥锁、条件锁、自旋锁、读写锁、递归锁。一般而言,所得功能与性能成反比。而且

C++线程中的几类锁

多线程中的锁主要有五类:互斥锁条件锁自旋锁读写锁递归锁。一般而言,所得功能与性能成反比。而且我们一般不使用递归锁(C++提供std::recursive_mutex),这里不做介绍。

互斥锁

==互斥锁用于控制多个线程对它们之间共享资源互斥访问的一个信号量。==也就是说为了避免多个线程在某一时刻同时操作一个共享资源,例如一个全局变量,任何一个线程都要使用初始锁互斥地访问,以避免多个线程同时访问发生错乱。

在某一时刻只有一个线程可以获得互斥锁,在释放互斥锁之前其它线程都不能获得互斥锁,以阻塞的状态在一个等待队列中等待。

头文件:#include

类型:std::std::mutex、std::lock_guard

用法:在C++中,通过构造std::mutex的实例创建互斥单元,调用成员函数lock()来锁定共享资源,调用unlock()来解锁。不过一般不使用这种解决方案,更多的是使用C++标准库中的std::lock_guard类模板,实现了一个互斥量包装程序,提供了一种方便的RaiI风格的机制在作用域块中。

关于RAII惯用法的介绍:。。。

示例代码:


#include <iOStream>
#include <thread>//C++11线程库是跨平台的
#include <mutex>//C++互斥锁
#include <vector>
#include <windows.h>
int g_num = 0;
std::mutex g_mutex;
void ThreadFunc(int a)
{
	cout << "启动线程:" << a << endl;
	for (int i = 0; i < 1000000; i++)
	{
		//g_mutex.lock();
		std::lock_guard<std::mutex> m(g_mutex);//互斥量包装程序
		g_num++;
		//g_mutex.unlock();
	}
}

int main()
{
	for (int i = 0; i < 4; i++)
	{
		std::thread t(ThreadFunc, i);
		t.detach();
	}
	Sleep(2000);
	cout << "g_num:" << g_num << endl;
	return 0;
}

//高阶版,将上述main()函数的函数名更改,再更改以下的mainTest()即可执行。两个方法的执行的结果相同,原理也相同。
int mainTest()
{
	std::vector<std::thread *> ts;
	for (int i = 0; i < 4; i++)
	{
		std::thread *t = new std::thread(ThreadFunc, i);
		//t.detach();
		ts.push_back(t);
	}
	for (auto begin = ts.begin(); begin != ts.end(); begin++)
		(*begin)->join();
	Sleep(2000);
	cout << "g_num:" << g_num << endl;
	return 0;
}

效果图

TIPS:注意std::cout和std::end都是线程不安全的,所以才会出现线程1和线程3在一行,原因就是线程1未执行cout<<endl。CPU的时间片就已经用完了,CPU转移执行线程3后,再执行线程1的cout<<endl。

具体C++11中thread库join和detach的区别可参考:https://www.jb51.net/article/229636.htm

条件锁

条件锁就是所谓的条件变量,当某一个线程因为某个条件未满足时可以使用条件变量使该程序处于阻塞状态,一旦条件满足则以“信号量”的方式唤醒一个因为该条件而被阻塞的线程。最为常见的就是再线程池中,初始情况下因为没有任务使得任务队列为空,此时线程池中的线程因为“任务队列为空”这个条件处于阻塞状态。一旦有任务进来,就会以信号量的方式唤醒该线程来处理这个任务。

自旋锁

互斥锁和条件锁都是比较常见的锁,比较容易理解。接下来用互斥锁和自旋锁的原理相互比较,来理解自旋锁。

假设我们有一台计算机,该计算机拥有两个处理器core1和core2.现在在这台计算机上运行两个线程:T1和T2,且T1和T2分别在处理器core1和core2上面运行,两个线程之间共享一份公共资源Public。

首先我们说明互斥锁的工作原理,互斥锁是一种sleep-waiting的锁。假设线程T1访问公共资源Public并获得互斥锁,同时在core1处理器上运行,此时线程T2也想要访问这份公共资源Public(即想要获得互斥锁),但是由于T1正在使用Public使得T2被阻塞。当T2处于阻塞状态时,T2被放入等待队列中,处理器core2会去处理其它的任务而不必一直等待(忙等)。也就是说处理器不会因为线程被阻塞而空闲,它会去处理其它事务

然后我们说明自旋锁的工作原理,自旋锁是一种busy-waiting的锁。也就是说,如果T1正在使用Public,而T2也想使用Public,此时T2肯定是得不到这个自旋锁的。与互斥锁相反,此时运行T2的处理器core2会一直不断地循环检查Public使用可用(自旋锁请求),直到获得到这个自旋锁为止。

从“自旋锁”的名称也可以看出,如果一个线程想要获得一个被使用的自旋锁,那么它会一直占用CPU请求这个自旋锁使得CPU不能去做其它的事情,知道获取这个锁为止,这就是“自旋”的含义。当发生阻塞时,互斥锁可以让CPU去处理其它的事务,但自旋锁让CPU一直不断循环请求获取这个锁。通过比较,我们可以明显的得出结论:“自旋锁”是比较消耗CPU的。

读写锁

读写锁我们可以借助于“读者-写者”问题进行理解。接下来我们简单说下“读者-写者”问题。

计算机中某些数据被多个进程共享,对数据库的操作有两种:一种是读操作,就是从数据库中读取数据不会修改数据库中内容;另一种就是写操作,写操作会修改数据库中存放的数据。因此可以得到我们允许在数据库上同时执行多个“读”操作,但是某一时刻只能在数据库上有一个“写”操作来更新数据。这就是简单的读者-写者模型。

参考博客

Https://www.jb51.net/article/214502.htm

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注编程网的更多内容!

--结束END--

本文标题: C++线程中几类锁的详解

本文链接: https://www.lsjlt.com/news/157744.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C++线程中几类锁的详解
    目录C++线程中的几类锁互斥锁条件锁自旋锁读写锁参考博客总结C++线程中的几类锁 多线程中的锁主要有五类:互斥锁、条件锁、自旋锁、读写锁、递归锁。一般而言,所得功能与性能成反比。而且...
    99+
    2024-04-02
  • C++线程中有几类锁
    这篇文章主要讲解了“C++线程中有几类锁”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++线程中有几类锁”吧!C++线程中的几类锁多线程中的锁主要有五类:互斥锁、条件锁、自旋锁、读写锁、递...
    99+
    2023-06-25
  • 详解C++11中的线程锁和条件变量
    目录线程锁条件变量小结线程 std::thread类, 位于<thread>头文件,实现了线程操作。std::thread可以和普通函数和 lambda 表达式搭配使用。...
    99+
    2024-04-02
  • Java多线程读写锁ReentrantReadWriteLock类详解
    目录ReentrantReadWriteLock读读共享写写互斥读写互斥源码分析写锁的获取与释放读锁的获取与释放参考文献真实的多线程业务开发中,最常用到的逻辑就是数据的读写,Reen...
    99+
    2024-04-02
  • C#线程开发之System.Thread类详解
    一、属性 CurrentContext    获取线程正在其中执行的当前上下文。ExecutionContext    获...
    99+
    2024-04-02
  • C语言多线程开发中死锁与读写锁问题详解
    目录死锁读写锁死锁 有时,一个线程需要同时访问两个或更多不同的共享资源,而每个资源又都由不同的互斥量管理。当超过一个线程加锁同一组互斥量时,就有可能发生死锁; 两个或两个以上的进程在...
    99+
    2024-04-02
  • 详解C++11中的线程库
    目录一、线程库的介绍1.1. 使用时的注意点1.2. 线程函数参数1.3. join与detach二、原子性操作库2.1. atomic2.2. 锁三、使用lambda表达式创建多个...
    99+
    2024-04-02
  • c#使用多线程的几种方式示例详解
    C#中使用多线程的几种方式有以下几种:1. 使用Thread类:Thread类是C#中最基本的多线程类,可以使用它创建和控制线程。下面是一个使用Thread类创建并启动线程的示例:```csharpusing System;using ...
    99+
    2023-08-09
    C#
  • C++多线程互斥锁和条件变量的详解
    目录互斥锁:std::mutex::try_lock         条件变量:condition_variable总结我们了解互斥...
    99+
    2024-04-02
  • c# Thread类线程常用操作详解
    目录创建线程 管理线程 销毁线程 创建线程 线程是通过扩展 Thread 类创建的。扩展的 Thread 类调用 Start() 方法来开始子线程的执行。 下面的程序演示...
    99+
    2024-04-02
  • 多线程之死锁详解
    死锁是指两个或多个线程在执行过程中,因争夺资源而造成的一种互相等待的现象,如果无外力干涉,这些线程将无法继续执行下去。死锁的产生通常...
    99+
    2023-09-13
    多线程
  • java 中断线程的几种方式 interrupt()详解
    中断   中断(Interrupt)一个线程意味着在该线程完成任务之前停止其正在进行的一切,有效地中止其当前的操作。线程是死亡、还是等待新的任务或是继续运行至下一步,就取决于这个程序...
    99+
    2024-04-02
  • C#多线程中的互斥锁Mutex
    一、简介 Mutex的突出特点是可以跨应用程序域边界对资源进行独占访问,即可以用于同步不同进程中的线程,这种功能当然这是以牺牲更多的系统资源为代价的。 主要常用的两个方法: publ...
    99+
    2024-04-02
  • Java解析线程的几种状态详解
    目录1. 线程的5种状态2. Java线程的6种状态3. Java线程状态的转换总结1. 线程的5种状态 从操作系统层面上,任何线程一般都具有五种状态,即创建、就绪、运行、阻塞、终止...
    99+
    2024-04-02
  • Java线程死锁代码详解
    public class JStackDemo { public static void main(String[] args) { Thread t1...
    99+
    2024-04-02
  • Java多线程之死锁详解
    目录1、死锁2、死锁经典问题——哲学家就餐问题 总结1、死锁 出现场景:当线程A拥有了A对象的锁,想要去获取B对象的锁;线程B拥有了B对象的锁,想要拥有A对象的锁,两个线程...
    99+
    2024-04-02
  • C#中类的使用教程详解
    目录实例化类成员访问赋值方法方法调用方法重载在对类访问使用时,常用到的有访问类的成员、方法。 实例化 在对类进行访问时,需要将类进行实例化。并产生一个对象。可以使用关键字new来实现...
    99+
    2024-04-02
  • 浅谈C++11中的几种锁
    目录互斥锁(mutex)条件锁(condition_variable)自旋锁(不推荐使用)递归锁(recursive_mutex)互斥锁(mutex) 可以避免多个线程在某一时刻同时...
    99+
    2024-04-02
  • MySQL中的锁可以分成几类
    本篇内容主要讲解“MySQL中的锁可以分成几类”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“MySQL中的锁可以分成几类”吧!根据加锁的范围,MySQL里面的锁...
    99+
    2024-04-02
  • C++详解多线程中的线程同步与互斥量
    目录线程同步互斥量线程同步 #include <stdio.h> #include <pthread.h> #include <unistd.h>...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作