操作系统——多线程同步互斥

本文详细介绍了Linux下处理线程同步的四种方法:互斥锁、条件变量、读写锁和信号量。互斥锁用于保证线程间的互斥访问,条件变量用于线程等待特定条件,读写锁允许多读单写,信号量则能解决多资源的同步问题。文章通过实例解析了各自的工作原理和应用场景。
摘要由CSDN通过智能技术生成

1. 思维导图

Linux下提供了多种方式来处理线程同步,最常用的是互斥锁、条件变量、信号量和读写锁。
下面是思维导图:
在这里插入图片描述

2. 各种解决方法的比较

并发有两大需求,一是互斥,二是等待。互斥是因为线程间存在共享数据,等待则是因为线程间存在依赖,需要同步。从上面可以看出,在Linux内核中有互斥锁、条件变量、读写锁、信号量4种机制用于解决线程间的同步和互斥问题,那这四种机制有何区别?

2.1 互斥锁

互斥量有两种状态–解锁和加锁。当一个线程(或进程)需要访问临界区时,它调用互斥锁。如果该互斥量当前是解锁的(即临界区可用),此调用成功,调用线程可以自由进入该临界区。另一方面,如果该互斥量已经加锁,调用线程被阻塞,直到在临界区中的线程完成并调用互斥锁。如果多个线程被阻塞在该互斥量上,将随机选择一个线程并允许它获得锁。

案例:这里有一个打印机p,A和B都要使用,显然只能轮流着使用。这时就需要加一个互斥锁,只有得到了互斥锁lock_s之后才能进行打印

pthread_mutex_lock(lock_s);
print();
pthread_mutex_unlock(lock_s);

2.2 条件变量(事件)

与互斥锁不同,条件变量是用来等待而不是用来上锁的。条件变量用来自动阻塞一个线程,直到某特殊情况发生为止。通常条件变量和锁机制同时使用。条件变量,是为了解决等待同步需求,实现生产者消费者队列的一种机制(得益于事件驱动模式——Actor,他也是基于异步AIO出现的,其实现在很多东西都是来自于Actor思想,比如IO多路复用、MapReduce、消息队列中间件(注意不是os中进程间通信的消息队列,这个消息队列中间件算是建立在应用层上的,而非os级的消息队列))。
在这里插入图片描述
  条件变量使我们可以睡眠等待某种条件出现。条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待"条件变量的条件成立"而挂起;另一个线程使 “条件成立”(给出条件成立信号)。
【原理】:
条件的检测是在互斥锁的保护下进行的。线程在改变条件状态之前必须首先锁住互斥量。如果一个条件为假,一个线程自动阻塞,并释放等待状态改变的互斥锁。如果另一个线程改变了条件,它发信号给关联的条件变量,唤醒一个或多个等待它的线程,重新获得互斥锁,重新评价条件。如果两进程共享可读写的内存,条件变量 可以被用来实现这两进程间的线程同步。
【条件变量的操作流程如下】:

1. 初始化:init()或者pthread_cond_tcond=PTHREAD_COND_INITIALIER;属性置为NULL2. 等待条件成立:pthread_wait,pthread_timewait.wait()释放锁,并阻塞等待条件变量为真 timewait()设置等待时间,仍未signal,返回ETIMEOUT(加锁保证只有一个线程wait)3. 激活条件变量:pthread_cond_signal,pthread_cond_broadcast(激活所有等待线程)
4. 清除条件变量:destroy;无线程等待,否则返回EBUSY清除条件变量:destroy;无线程等待,否则返回EBUSY

案例:生产者P每次只能生产1个配件part,消费者A和B必须要等到有100个配件才能进行装配。
如果我们只用互斥锁的话,那消费者就得互斥地方式不断轮询共享的全局变量part,查看其数量是否大于等于100。如果是队列里有值,就去消费;如果为空,要么是继续查( spin 策略),要么 sleep 一下,让系统过一会再唤醒你,你再次查。可以想到,无论哪种策略,都不通用,要么费 cpu,要么线程 sleep过头了,影响该线程的性能。

//poll轮询
#define assembleMutex
P:
	part++
A/B:
	
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值