理解互斥量和信号量 作者: JuKevin

2023-11-14

理解互斥量和信号量 作者: JuKevin

 

 互斥量(Mutex)

 

互斥量表现互斥现象的数据结构,也被当作二元信号灯。一个互斥基本上是一个多任务敏感的二元信号,它能用作同步多任务的行为,它常用作保护从中断来的临界段代码并且在共享同步使用的资源。

 

 Mutex本质上说就是一把锁,提供对资源的独占访问,所以Mutex主要的作用是用于互斥。Mutex对象的值,只有0和1两个值。这两个值也分别代表了Mutex的两种状态。值为0, 表示锁定状态,当前对象被锁定,用户进程/线程如果试图Lock临界资源,则进入排队等待;值为1,表示空闲状态,当前对象为空闲,用户进程/线程可以Lock临界资源,之后Mutex值减1变为0。

 

Mutex可以被抽象为四个操作:

 

- 创建

 Create -

 

加锁

Lock -

 

 解锁

Unlock -

 

销毁

Destroy Mutex

 

被创建时可以有初始值,表示Mutex被创建后,是锁定状态还是空闲状态。在同一个线程中,为了防止死锁,系统不允许连续两次对Mutex加锁(系统一般会在第二次调用立刻返回)。也就是说,加锁和解锁这两个对应的操作,需要在同一个线程中完成。

 

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

动作/系统 Win32 Linyx Solaris

创建

CreateMutex

pthread_mutex_init

 mutex_init

 

 加锁

WaitForSingleObject

 pthread_mutex_lock

 mutex_lock

 

 解锁

 ReleaseMutex

pthread_mutex_unlock

 mutex_unlock

 

 销毁

CloseHandle

pthread_mutex_destroy

 mutex_destroy

 

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

 

信号量可以分为几类:

 

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

 

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

 

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

 

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

 

计数器计算的结果是允许访问共享资源的通行证。因此,为了访问共享资源,线程必须从信号量得到通行证, 如果该信号量的计数大于0,则此线程获得一个通行证,这将导致信号量的计数递减,否则,此线程将阻塞直到获得一个通行证为止。当此线程不再需要访问共享资源时,它释放该通行证,这导致信号量的计数递增,如果另一个线程等待通行证,则那个线程将在那时获得通行证。

 

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

- 创建 Create -

等待 Wait: 线程等待信号量,如果值大于0,则获得,值减一;如果只等于0,则一直线程进入睡眠状态,知道信号量值大于0或者超时。

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

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

-销毁 Destroy

 

信号量,是可以用来保护两个或多个关键代码段,这些关键代码段不能并发调用。在进入一个关键代码段之前,线程必须获取一个信号量。如果关键代码段中没有任何线程,那么线程会立即进入该框图中的那个部分。一旦该关键代码段完成了,那么该线程必须释放信号量。其它想进入该关键代码段的线程必须等待直到第一个线程释放信号量。为了完成这个过程,需要创建一个信号量,然后将Acquire Semaphore VI以及Release Semaphore VI分别放置在每个关键代码段的首末端。确认这些信号量VI引用的是初始创建的信号量。

 

动作/系统 Win32 POSIX

 

创建

 CreateSemaphore

sem_init

 

等待

WaitForSingleObject

sem _wait

 

释放

 ReleaseMutex sem _post

 

试图等待

WaitForSingleObject

 sem _trywait

 

销毁

CloseHandle

sem_destroy

 

互斥量和信号量的区别

 1. 互斥量用于线程的互斥,信号线用于线程的同步。 这是互斥量和信号量的根本区别,也就是互斥和同步之间的区别。 互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。 同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源

 

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

 

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

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

理解互斥量和信号量 作者: JuKevin 的相关文章

  • Java无限信号量

    想知道如何not使用信号量限制连接 或任何东西 所以你可能会想 这听起来很愚蠢 但是 它稍微简化了我的代码 因为它让我可以统一处理有限和无限的情况 请注意 我并不是在寻找有关如何编写类似内容的建议 if limited semaphore
  • 如何对无法存储在一个变量中的大数字进行运算

    在Java中 我希望能够对非常大的整数 不能存储在long中 进行操作 我该怎么做 在表现良好的情况下 处理这个问题的最佳方法是什么 我应该创建自己的包含多个长变量的数据类型吗 Example public class MyBigInteg
  • Android:等待 firebase valueEventListener

    我正在尝试使用信号量来等待我的 firebase valueEventListener 我有一个用户信息活动 其中包含用户必须填写的 6 个不同字段 当用户保存他 她的信息时 我想进行 全有或全无 类型的检查 某些用户信息不能重复 例如用户
  • 我可以在C中直接比较int和size_t吗?

    我可以比较一个int and a size t像这样的变量 int i 1 size t y 2 if i y Do something 或者我必须输入其中之一 只要满足以下条件 它就是安全的int为零或正数 如果它是负数 并且size t
  • 将 2 个字节转换为整数

    我收到一个 2 个字节的端口号 最低有效字节在前 我想将其转换为整数 以便我可以使用它 我做了这个 char buf 2 Where the received bytes are char port 2 port 0 buf 1 port
  • 正则表达式查找字符串中的整数和小数

    我有一个像这样的字符串 str1 12 ounces str2 1 5 ounces chopped 我想从字符串中获取金额 无论它是否是小数 12 或 1 5 然后获取紧邻的前一个测量值 盎司 我能够使用一个非常基本的正则表达式来获取测量
  • 如何同时接受int和float类型的输入?

    我正在制作一个货币转换器 如何让 python 同时接受整数和浮点数 我就是这样做的 def aud brl amount From to ER 0 42108 if amount int if From strip aud and to
  • 如何将十六进制颜色字符串解析为整数

    我正在 Robolectric 中编写一些代码 即IntegerResourceLoader 下面的方法抛出一个RuntimeException when rawValue是诸如0xFFFF0000 Override public Obje
  • 在 String 值之后打印 int 值

    我有以下示例代码 int pay 80 int bonus 65 System out println pay bonus bonus pay 有人可以向我解释一下为什么我得到以下输出 145 6580 您的代码正在从左到右解释表达式 pa
  • 将数字转换为整数列表[重复]

    这个问题在这里已经有答案了 我该如何写magic下面的函数 gt gt gt num 123 gt gt gt lst magic num gt gt gt gt gt gt print lst type lst 1 2 3
  • 负整数的Python表示

    gt gt gt x 4 gt gt gt print b format x x 4 100 gt gt gt mask 0xFFFFFFFF gt gt gt print b format x mask x mask 4294967292
  • 如果我的编译器不支持 C 或 C++ 中的 128 位整数加法和减法?

    我正在为 128 位数字的长流编写一个压缩器 我想将数字存储为差异 仅存储数字之间的差异而不是数字本身 因为我可以将差异打包在更少的字节中 因为它们更小 然而 为了压缩 我需要减去这些 128 位值 为了解压缩 我需要添加这些值 我的编译器
  • 四个无符号整数的哈希函数 (C++)

    我现在正在编写一个程序 它生成四个无符号 32 位整数作为某个函数的输出 我想对这四个整数进行哈希处理 这样我就可以将该函数的输出与未来的输出进行比较 不过 我在编写一个像样的哈希函数时遇到了麻烦 当我最初编写这段代码时 我对四个整数分别进
  • Android:转换为位图时,回收器视图的宽度和高度必须> 0

    在 Sqlite 中存储文本和图像 并尝试将这些数据检索到 recyclerview 中 当将图像显示到 recyclerview 中时 它显示错误宽度和高度必须 gt 0 在将图像保存在 sqlite 中时 我将位图转换为字节 数据库助手
  • C语言中使用POSIX使二进制信号量在多个进程(不是线程,仅限进程)之间共享

    我正在使用 C 语言中的 POSIX 使二进制信号量在多个进程 不是线程 仅进程 之间共享 如果我使用互斥体创建二进制信号量 typedef struct BIN SEMA pthread cond t cv cond variable u
  • Java中有默认的数字类型吗

    如果我写这样的东西 System out println 18 哪种类型有 18 是吗int or byte 或者它还没有类型 它不能是 int 因为这样的东西是正确的 byte b 3 这是不正确的 int i 3 byte bb i e
  • C 常用算术转换

    我正在阅读 C99 标准中有关常见算术转换的内容 如果两个操作数具有相同的类型 则无需进一步转换 需要 否则 如果两个操作数都有符号整数类型或者都有 无符号整数类型 较小整数类型的操作数 转换等级转换为大于操作数的类型 秩 否则 如果具有无
  • 在 Python 中将 int 转换为字符串

    我希望能够生成多个名为 fileX txt 的文本文件 其中 X 是某个整数 for i in range key filename ME i txt Error here Can t concat a string and int fil
  • 在 Python 中使用带有 asyncio 的信号量

    我试图限制使用信号量同时运行的异步函数的数量 但我无法让它工作 我的代码归结为 import asyncio async def send i print f starting i await asyncio sleep 4 print f
  • 读写器的信号量解决方案:更新读取器计数和等待或发出读/写二进制信号量信号之间的顺序?

    从操作系统概念来看 在解决第一个读者 作者问题时 读者 进程共享以下数据结构 semaphore rw mutex 1 semaphore mutex 1 int read count 0 do wait rw mutex writing

随机推荐