互斥锁Mutex和信号量

2023-05-16

 

Mutex是一把钥匙,一个人拿了就可进入一个房间,出来的时候把钥匙交给队列的第一个。一般的用法是用于串行化对critical section代码的访问,保证这段代码不会被并行的运行。

 

Is a key to a toilet. One person can have the key - occupy the toilet - at the time. When finished, the person gives (frees) the key to the next person in the queue.

Officially: "Mutexes are typically used to serialise access to a section of re-entrant code that cannot be executed concurrently by more than one thread. A mutex object only allows one thread into a controlled section, forcing other threads which attempt to gain access to that section to wait until the first thread has exited from that section."

Semaphore是一件可以容纳N人的房间,如果人不满就可以进去,如果人满了,就要等待有人出来。对于N=1的情况,称为binary semaphore。一般的用法是,用于限制对于某一资源的同时访问。

 

Semaphore:

Is the number of free identical toilet keys. Example, say we have four toilets with identical locks and keys. The semaphore count - the count of keys - is set to 4 at beginning (all four toilets are free), then the count value is decremented as people are coming in. If all toilets are full, ie. there are no free keys left, the semaphore count is 0. Now, when eq. one person leaves the toilet, semaphore is increased to 1 (one free key), and given to the next person in the queue.

Officially: "A semaphore restricts the number of simultaneous users of a shared resource up to a maximum number. Threads can request access to the resource (decrementing the semaphore), and can signal that they have finished using the resource (incrementing the semaphore)." Ref: Symbian Developer Library

信号量限制一份资源的最大同步个数。线程可以请求进入资源,并在用完资源时发出信号.

对于Binary semaphore与Mutex,这两者之间就存在了很多相似之处:
在有的系统中Binary semaphore与Mutex是没有差异的。在有的系统上,主要的差异是mutex一定要由获得锁的进程来释放。而semaphore可以由其它进程释放(这时的semaphore实际就是个原子的变量,大家可以加或减),因此semaphore可以用于进程间同步。Semaphore的同步功能是所有系统都支持的,而Mutex能否由其他进程释放则未定,因此建议mutex只用于保护critical section。而semaphore则用于保护某变量,或者同步。

1、Mutex 互斥量/互斥锁

Mutex本质上说就是一把锁,提供对资源的独占访问,所以Mutex的主要作用是用于互斥的访问共享资源

Mutex对象的值,只有0和1两个值。这两个值也分别代表了Mutex的两种状态。

值为0,表示锁定状态,当前对象被锁定,用户进程/线程如果试图Lock临界资源,则进入排队等待。

值为1,表示空闲状态,当前对象为空闲,用户进程/线程可以Lock临界资源,之后Mutex值减1变为0.

Mutex可以被抽象为四个操作:创建 Create;加锁 Lock;解锁 Unlock;销毁 Destroy。

Mutex被创建时可以有初始值,表示Mutex被创建后,是锁定状态还是空闲状态。

在同一个线程中,为了防止死锁,系统不允许连续两次对Mutex加锁。就是加锁和解锁这两个对应的操作,需要在同一个线程中完成

不同操作系统中提供的Mutex函数:

 

动作/系统WindowsLinuxSolaris
创建CreateMutexpthread_mutex_initmutex_init
加锁WaitForSingleObjectpthread_mutex_lockmutex_lock
解锁ReleaseMutexpthread_mutex_unlockmutex_unlock
销毁CloseHandlepthread_mutex_destroymutex_destroy

避免互斥锁死锁的几个基本原则:

-- 对共享资源操作前一定要获得锁。

-- 完成操作以后一定要释放锁。

-- 尽量短时间的占用锁,即占用锁的时间不要过长。

-- 如果有多锁,如获得顺序是ABC连环扣,释放顺序也应该是ABC。

-- 线程错误返回时应该释放它所获得的锁。

>>“挂起等待”和“唤醒等待线程”的操作?

每个Mutex有一个等待队列,一个线程要在Mutex上挂起等待,首先把自己加入等待队列中,然后置线程状态为睡眠,然后调用调度器函数切换到别的线程。一个线程要唤醒等待队列中的其它线程,只需从等待队列中取出一项,把它的状态从睡眠改为就绪,加入就绪队列,那么下次调度器函数执行时就有可能切换到被唤醒的线程。

一般情况下,如果同一个线程先后两次调用lock,在第二次调用时,由于锁已经被占用,该线程会挂起等待别的线程释放锁,然而锁正是被自己占用着的,该线程又被挂起而没有机会释放锁,因此就永远处于挂起等待状态了,这叫做死锁(Deadlock)。

另一种典型的死锁情形是这样:线程A获得了锁1,线程B获得了锁2,这时线程A调用lock试图获得锁2,结果是需要挂起等待线程B释放锁2,而这时线程B也调用lock试图获得锁1,结果是需要挂起等待线程A释放锁1,于是线程A和线程B都永远处于挂起状态了。如果涉及更多的线程和更多的锁,则死锁的可能性更大。(例子,上厕所,要锁厕所门)

2、信号量 semaphore

信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施,它负责协调各个线程,以保证它们能够正确、合理的使用公共资源。信号量可以分为几类:

-- 二进制信号量(binary semaphore):只允许信号量取0或1值,其同时只能被一个线程获取。

-- 整型信号量(integer semaphore):信号量取值是整数,它可以被多个线程同时获得,直到信号量的值变为0.

-- 记录型信号量(record semaphore):每个信号量s除一个整数值value(计数)外,还有一个等待队列List,其中是阻塞在该信号量的各个线程的标识。当信号量被释放一个,值被加1后,系统自动从等待队列中唤醒一个等待中的线程,让其获得信号量,同时信号量再减1.

信号量通过一个计数器控制对共享资源的访问,信号量的值是一个非负整数,所有通过它的线程都会将该整数减1.如果计数器大于0,则访问被允许;如果为0,则访问被禁止,所有试图通过它的线程都将处于等待状态。

计数器计算的结果是允许访问共享资源的通行证。因此,为了访问共享资源,线程必须从信号量得到通行证,如果该信号量的计数大于0,则此线程获得一个通行证,这将导致信号量的计数递减,否则,此线程将阻塞直到获得一个通行证为止。

当此线程不再需要访问共享资源时,它释放该通行证,这导致信号量的计数递增,如果另一个线程等待通行证,则那个线程将在那时获得通行证。

Semaphore可以被抽象为5个操作:

>> 创建 Create

>> 等待 Wait,线程等待信号量,如果值>0,则获得,值减1;如果<=0,则线程进入睡眠状态,直到信号量值>0或超时。

>> 释放 Post,执行释放信号量,则值加+1,如果此时有正在等待的线程,则唤醒该线程。

>> 试图等待 TryWait,线程并不真正的去获得信号量,而是检查信号量是否能够被获得,如果信号量值大于0,则TryWait返回成功,否则返回失败。

>> 销毁 Destroy

信号量,是可以用来保护两个或多个关键代码段,这些关键代码段不能并发调用。在进入一个关键代码段之前,线程必须获取一个信号量。首先要创建一个信号量,然后将Acquire Semaphore 以及Release Semaphore分别放置在每个关键代码段的首末段。

POSIX Semaphore(Named Semaphores / Unnamed Semaphores)

Named Semaphores:this type of semaphore has a name. By calling sem_open() with the same name, unrelated process can access the same semaphore.

To work with a named semaphore, we employ the following functions:

-- The sem_open() function opens or create a semaphore, initializes the semaphore if it is created by the call, and returns a handle for use in later calls.

-- The sem_post(sem) and sem_wait(sem) functions respectively increment and decrement a semaphore's value.

-- The sem_getvalue() function retrieves a semaphore's current value.

-- The sem_close() function removes the calling process's association with a semaphore that it previously opened.

-- The sem_unlink() function removes a semaphore name and marks the semaphore for deletion when all processes have closed it.

3)互斥量和信号量的区别:

>> 互斥量用于线程的互斥,信号量用于线程的同步。

这是互斥量和信号量的根本区别,也就是互斥和同步之间的区别。

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

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

>> 互斥量值只能是0/1,信号量值可以为非负整数。

也就是说,一个互斥量只能用于一个资源的互斥访问,它不能实现多个资源的多线程互斥问题。信号量可以实现多个同类资源的多线程互斥和同步。当信号量为单值信号量时,也可以完成一个资源的互斥访问。

>> 互斥量的加锁和解锁必须由同一线程分别对应使用,信号量可以由一个线程释放,另一个线程得到。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

互斥锁Mutex和信号量 的相关文章

随机推荐

  • python logging.info在终端没输出

    问题描述 在pyhton脚本中logging info 34 hello world 34 希望输出 39 hello world 39 但是在终端没有输出 解决方法 在文件开始的地方添加以下内容 span class pln style
  • ImportError: libSM.so.6: cannot open shared object file: No such file or directory解决

    运行如下命令即可解决 span class pln style margin 0px padding 0px border 0px font style inherit font weight inherit font size 6 lin
  • linux 查看版本信息

    1 uname xff0d a xff08 Linux查看版本当前操作系统内核信息 xff09 Linux ml 4 4 0 109 generic 132 Ubuntu SMP Tue Jan 9 19 52 39 UTC 2018 x8
  • 你真的了解串口吗(示波器串口波形分析)

    串口是最常用的外设了 xff0c 串口基本都是单片机的标配 串口通信只需要3条线组成 xff0c 分别为RX TX GND 下面将重点分析串口数据帧组成 一 串口通信帧 串口通信帧数据如此 xff0c 每帧由空闲位 起始位 数据位 校验位
  • C++——类和对象(4)

    作者 xff1a 几冬雪来 时间 xff1a 2023年5月6日 内容 xff1a C 43 43 类和对象内容讲解 目录 前言 xff1a 1 运算符重载 xff08 续 xff09 xff1a 2 赋值重载 xff1a 结尾 xff1a
  • Shell脚本-NF、FS(OFS)、RS(ORS)、NR(FNR)

    1 NF xff1a number of fileds xff08 字段 域的个数 xff09 整数 NF xff1a 取最后一列的字符串 xff0c 等同于 1 2 xff0c NF 1 NF等等 来看个例子吧 kdvmt 64 kdvm
  • 七月历程

    六月底老师通知让我提前返校 xff0c 去长春自我隔离一段时间 xff0c 这几天一直在收拾东西 空余时间没用来学习 xff0c 不过倒是上 steam 上买了个游戏 QAQ 2020 是个多灾多难的年份 澳洲火灾 xff0c 东非蝗虫肆虐
  • Shell脚本 - cut、sort、paste

    1 cut xff1a 用来提取文件的片段 d 后面指定分隔的符号 f 指定显示第几列 c 后面跟显示的字符1 n xff0c character b 后面根据显示的字节 xff0c byte kdvmt 64 kdvmt temp cat
  • 儿童诗词学习

    鹿寨 xff08 王维 xff09 空山不见人 xff0c 但闻人语响 返景入深林 xff0c 复照青苔上 独坐敬亭山 xff08 李白 xff09 众鸟高飞尽 xff0c 孤云独去闲 相看两不厌 xff0c 只有敬亭山 杂诗 xff08
  • 分页存储管理中的页表项长度是什么?

    看到很多人有疑问 xff1f 读到这里的时候我也有疑问的 在操作系统的分页存储管理方式中 xff0c 写道 xff1a 将页表始址与页号和页表项长度的乘积 相加 xff0c 便得到该表项在页表中的位置 于是可从中得到该页的物理块号 xff0
  • apt-get和aptitude

    1 apt get apt get是一条linux命令 xff0c 适用于deb包管理式的操作系统 xff0c 主要用于自动从互联网的软件仓库中搜索 安装 升级 卸载软件或操作系统 Advanced Package Tool xff0c 又
  • SPOOLing技术

    虚拟性是OS的四大特征之一 如果说可以通过多道程序技术 将一台物理CPU虚拟为多台 逻辑CPU xff0c 从而允许多个用户共享一台主机 xff0c 那么通过SPOOLing技术 便可将一台物理I O设备虚拟为多台 逻辑I O设备 xff0
  • C语言 gets()和scanf()函数的区别

    scanf 函数和gets 函数都可用于输入字符串 xff0c 但在功能上有区别 若想从键盘上输入字符串 34 hi hello 34 xff0c 则应该使用gets 函数 gets可以接收空格 xff1b 而scanf遇到空格 回车和Ta
  • vector删除元素之pop_back(),erase(),remove()

    向量容器vector的成员函数pop back 可以删除最后一个元素 而函数erase 可以删除由一个iterator指出的元素 xff0c 也可以删除一个指定范围的元素 还可以采用通用算法 remove 来删除vector容器中的元素 x
  • setw()使用方法

    1 setw xff08 int n xff09 只是对直接跟在 lt lt 后的输出数据起作用 xff0c 而在之后的 lt lt 需要在之前再一次使用setw xff1b xff08 Sets the number of charact
  • 主存到Cache直接映射、全相联映射和组相联映射

    Cache的容量很小 xff0c 它保存的内容只是主存 xff08 内存 xff09 内容的一个子集 xff0c 且Cache与主存的数据交换是以块 xff08 cache line xff09 为单位的 为了把信息放到Cache中 xff
  • 图的存储结构-十字链表和邻接多重表

    1 十字链表 对于有向图来说 xff0c 邻接表是有缺陷的 关心了出度问题 xff0c 想了解入度就必须要遍历整个图才能知道 反之 xff0c 逆邻接表 解决了入度 却不了解出度的情况 有没有可能把邻接表和逆邻接表结合起来呢 xff1f 答
  • U3D开发的逆天级大型游戏有哪些

    1 World of Diving 潜水世界 一款潜水游戏 潜水世界 xff1a http dx60 downyouxi com qianshuishijie zip 氛围不错 xff0c 不过细看建模好像不是特别精细的样子 2 The F
  • 中断屏蔽技术

    1 中断屏蔽技术 xff1a 主要用于多重中断 多重中断 xff1a xff08 中断嵌套 xff09 当CPU 正在执行某个中断服务程序时 xff0c 另一个中断源又提出了新的中断请求 xff0c 而CPU 又响应了这个新的请求 xff0
  • 互斥锁Mutex和信号量

    Mutex是一把钥匙 xff0c 一个人拿了就可进入一个房间 xff0c 出来的时候把钥匙交给队列的第一个 一般的用法是用于串行化对critical section代码的访问 xff0c 保证这段代码不会被并行的运行 Is a key to