1、互斥量:采用互斥对象机制,只有拥有互斥对象的线程才有访问公共资源的权限。因为互斥对象只有一个,所以可以保证公共资源不会被多个线程同时访问。
2、信号量:它允许同一时刻多个线程访问同一资源,但是需要控制同一时刻访问此资源的最大线程数量。
3、事件(信号):通过通知操作的方式来保持多线程同步,还可以方便的实现多线程优先级的比较操作。
拓展阅读: 线程同步的几种方式
解析:
首先要明白,什么是线程同步,为什么要同步?所谓同步,就是并发的线程在一些关键点上可能需要互相等待与互通信息,这种相互制约的等待与互通信息称为进程同步。
“同”其实是协同,而不是同时,因为我们知道多线程终究是不能同时执行的(看起来那么多程序同时运行互相不干扰那是从宏观层面看是这样),那么线程之间由于执行权在不断地切换,如果不同线程都做不同的事,处理不同的数据倒也没什么问题,关键是有时候会有那么一些数据,是被多个线程共享的,大家都有可能对这些数据进行一些操作。
比如,银行系统同时收到两个请求向同一个账户A存钱,都是要存入100元.账户A中本来有1000元。那么系统对两个请求肯定是分别生成一个线程去完成各自的对账户进行加上100元的操作,可是当其中一个线程1运行完以下语句:
account=account+100
当线程1读取到account在内存中的值1000并加上了100得到1100,但还没更新到数据库中时,线程1由于丧失了执行权,线程2来接手了,线程2也执行这一句,但它读到的account值依然是1000(数据库的数据尚未更新),也把它加上100,变成1100,然后要更新到数据库。那后面不管谁先更新到数据库,数据库里A账户的记录都只会是1100,而不是1200了,这就出岔子了。
要防范这种问题也不难,我们可以让给执行账户值更改一直到把新的值更新到数据库里的整个操作给”封闭“起来,一次只允许一个线程来对同一个账户执行这样一些操作,如果多个线程想同时来执行这个操作,对不起,因为这些操作被”封闭“了,不等里面的一个线程把它要做的修改更新到数据库之前,其它线程一概不许进入,乖乖在外面排队等着吧。
这只是一个简单的例子,于是我们需要一些机制来保证这样的问题不会出现,让不同的线程在操作这样一些共同的数据时不会出问题,再或者是有时候有些事必须等A线程做完了,B线程才能接着后面的做,我们要让这些需要多个线程合作的任务都正常进行,因此就要让它们”同步“!
这里再引入一个临界资源与临界区的概念:
临界资源是指一次仅允许一个线程使用的资源,许多物理设备,如打印机都有这种性质。除了物理设备外,还有一些软件资源,若被多线程所共享也具有这一特点,如变量、数据、表格、队列等。它们虽可以为若干线程所共享,但一次只能为一个线程所利用。
临界区指的是一个访问共用资源(被多个线程共享的临界资源)的程序片段,而这些共用资源又无法同时被多个线程访问的特性。当有线程进入临界区段时,其他线程或是进程必须等待(例如:bounded waiting 等待法),有一些同步的机制必须在临界区段的进入点与离开点实现,以确保这些共用资源是被互斥获得使用,例如:semaphore。只能被单一线程访问的设备,例如:打印机。
同步有以下这样些个方式/机制:
(1)互斥量(mutex):互斥量是一种公共资源,在指定时刻,它只能被一个线程占有(也就是所有权特性),而且占有它的线程可以反复申请这个互斥量。只有拥有互斥量的线程才有访问公共资源的权限。因为互斥量只有一个,所以可以保证公共资源不会被多个线程同时访问。(比如Java中的synchronized代码块,需要你提供一个类的对象或Class类作为锁,这个锁就可以理解为互斥量)
(2)信号量(semaphore):每个信号量都是公共资源,其值是一个32位计数。信号量的数据结构为一个值和一个指针,指针指向等待该信号量的下一个进程。信号量的值与相应资源的使用情况有关。当它的值大于0时,表示当前可用资源的数量;当它的值小于0时,其绝对值表示等待使用该资源的进程个数。注意,信号量的值仅能由PV操作来改变。
实现的P,V操作算法描述:
P操作:while s>0
s=s-1,
V操作:s=s+1。
P表示申请一个资源,如果条件满足(即右可以分配的资源),则把资源分配给提出申请的进程,并且时资源数目s减1。V表示资源使用哪完毕之后,要把占有的资源释放,并且资源数目s加1 。
(3)事件(信号 signal):通过通知操作的方式来保持多线程同步,还可以方便的实现多线程优先级的比较操作。(比如Java中的notify()唤醒wait()状态的阻塞线程)
上一题:进程的通信方式有哪些?
下一题:操作系统中进程调度策略有哪几种?
标签: 互斥、线程、公共资源、同步、时刻
笔试题
刷题
简历模板
AI算法
大数据
内推