首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

详解Linux多线程中的互斥锁、读写锁、自旋锁、条件变量、信号量

本篇来聊一聊Linux中多线程编程中的重要知识点,详细谈谈多线程中同步和互斥机制。

同步和互斥

互斥:多线程中互斥是指多个线程访问同一资源时同时只允许一个线程对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的;

同步:多线程同步是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源。

互斥锁

在多任务操作系统中,同时运行的多个任务可能都需要使用同一种资源。为了同一时刻只允许一个任务访问资源,需要用互斥锁对资源进行保护。互斥锁是一种简单的加锁的方法来控制对共享资源的访问,互斥锁只有两种状态,即上锁( lock )和解锁( unlock )。

互斥锁操作基本流程

访问共享资源前,对互斥锁进行加锁

完成加锁后访问共享资源

对共享资源完成访问后,对互斥锁进行解锁

互斥锁特性

:互斥锁是一个原子操作,操作系统保证如果一个线程锁定了一个互斥锁,那么其他线程在同一时间不会成功锁定这个互斥锁

:如果一个线程锁定了一个互斥锁,在它解除锁之前,其他线程不可以锁定这个互斥锁

:如果一个线程已经锁定了一个互斥锁,第二个线程又试图去锁定这个互斥锁,则第二个线程将被挂起且不占用任何CPU资源,直到第一个线程解除对这个互斥锁的锁定为止,第二个线程则被唤醒并继续执行,同时锁定这个互斥锁

示例

读写锁

读写锁允许更高的并行性,也叫共享互斥锁。互斥量要么是加锁状态,要么就是解锁状态,而且一次只有一个线程可以对其加锁。读写锁可以有3种状态:。一次只有一个线程可以占有写模式的读写锁,但是多个线程可以同时占有读模式的读写锁,即允许多个线程读但只允许一个线程写。

当读操作较多,写操作较少时,可用读写锁提高线程读并发性

读写锁特性

如果有线程读数据,则允许其它线程执行读操作,但不允许写操作

如果有线程写数据,则其它线程都不允许读、写操作

如果某线程申请了读锁,其它线程可以再申请读锁,但不能申请写锁

如果某线程申请了写锁,其它线程不能申请读锁,也不能申请写锁

读写锁适合于对数据的读次数比写次数多得多的情况

读写锁创建和销毁

参数:rwlock:读写锁,attr:读写锁属性

返回值:成功返回0,出错返回错误码

读写锁加锁解锁

参数:rwlock:读写锁

返回值:成功返回 0;出错,返回错误码

示例

结果

自旋锁

自旋锁与互斥锁功能相同,唯一不同的就是互斥锁阻塞后休眠不占用CPU,而自旋锁阻塞后不会让出CPU,会一直忙等待,直到得到锁

自旋锁在用户态较少用,而在内核态使用的比较多

自旋锁的使用场景:锁的持有时间比较短,或者说小于2次上下文切换的时间

自旋锁在用户态的函数接口和互斥量一样,把中mutex换成spin,如:

自旋锁函数

linux中的自旋锁用结构体spinlock_t 表示,定义在。自旋锁的接口函数全部定义在头文件中,实际使用时只需即可

示例

条件变量

条件变量用来阻塞一个线程,直到条件发生。通常条件变量和互斥锁同时使用。条件变量使线程可以睡眠等待某种条件满足。条件变量是利用线程间共享的全局变量进行同步的一种机制。

条件变量的逻辑:一个线程挂起去等待条件变量的条件成立,而另一个线程使条件成立。

基本原理

线程在改变条件状态之前先锁住互斥量。如果条件为假,线程自动阻塞,并释放等待状态改变的互斥锁。如果另一个线程改变了条件,它发信号给关联的条件变量,唤醒一个或多个等待它的线程。如果两进程共享可读写的内存,条件变量可以被用来实现这两进程间的线程同步

示例

结果

虚假唤醒

当线程从等待已发出信号的条件变量中醒来,却发现它等待的条件不满足时,就会发生虚假唤醒。之所以称为虚假,是因为该线程似乎无缘无故地被唤醒了。但是虚假唤醒不会无缘无故发生:它们通常是因为在发出条件变量信号和等待线程最终运行之间,另一个线程运行并更改了条件

避免虚假唤醒

在wait端,我们必须把判断条件和wait()放到while循环中

信号量

信号量用于进程或线程间的同步和互斥,信号量本质上是一个非负的整数计数器,它被用来控制对公共资源的访问。编程时可根据操作信号量值的结果判断是否对公共资源具有访问的权限,当信号量值大于0时,则可以访问,否则将阻塞

示例

结果

结束语

通过这篇文章希望对小伙伴们有所帮助,希望能更深刻的理解多线程编程中的知识。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20230227A011JG00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券