本文介绍了“窗口中信号量和互斥量的区别是什么”的知识。很多人在实际案件操作中都会遇到这样的困难。接下来,让边肖带领大家学习如何应对这些情况!希望大家认真阅读,学点东西!
区别:1。互斥量用于线程互斥,信号量用于线程同步;2.互斥值只能为0或1,信号值可以为非负整数;3.互斥锁的锁定和解锁必须分别由同一个线程使用,信号量可以由一个线程释放,由另一个线程获取。
本教程的操作环境:windows7系统,戴尔G3电脑。
互斥量和信号量的区别
1. 互斥量用于线程的互斥,信号量用于线程的同步。
这就是互斥和信号量的根本区别,也就是互斥和同步的区别。
互斥:当一个资源只允许一个访问者同时访问时,它是唯一的。但是互斥不能限制访问者对资源的访问顺序,即访问无序。
同步:指访问者在互斥的基础上(多数情况下)通过其他机制有序地访问资源。在大多数情况下,同步已经实现了互斥,尤其是当所有写入的资源都是互斥的时候。在极少数情况下,可以允许多个访问者同时访问资源。
2. 互斥量值只能为0/1,信号量值可以为非负整数。
也就是说,一个互斥体只能用于一个资源的互斥访问,不能实现多个资源的多线程互斥问题。信号量可以实现多个相似资源的多线程互斥和同步。当信号量是单值信号量时,它也可以完成对资源的独占访问。
3. 互斥量的加锁和解锁必须由同一线程分别对应使用,信号量可以由一个线程释放,另一个线程得到。
00-1010互斥是显示互斥现象的数据结构,也被认为是二进制信号灯。互斥体基本上是多任务敏感的二进制信号,可以作为同步多任务行为。它通常用于保护关键部分代码免受中断,并共享同步使用的资源。
Mutex本质上是一个提供独占访问资源的锁,所以Mutex主要用于互斥。Mutex对象的值只有两个值:0和1。这两个值也代表Mutex的两种状态。值为0表示锁定状态,当前对象被锁定,如果用户进程/线程试图锁定关键资源,将进入等待队列;值1表示空闲状态,当前对象空闲,用户进程/线程可以锁定关键资源,然后Mutex值减少1到0。
互斥可以抽象为四种操作:
-创建创建
-锁锁
-解锁。
摧毁摧毁
互斥体在创建时可以有一个初始值,指示互斥体在创建后是被锁定还是空闲。在同一个线程中,为了防止死锁,系统不允许Mutex连续锁定两次(系统通常在第二次调用后立即返回)。也就是说,相应的锁定和解锁操作需要在同一个线程中完成。
不同操作系统中提供的互斥功能:
行动/系统
Win32
Linyx
Solaris
建立
创建互斥体
pthread_mutex_init
互斥初始化
锁
WaitForSingleObject
pthread_mutex_lock
互斥锁
/td>
解锁
ReleaseMutex
pthread_mutex_unlock
mutex_unlock
销毁
CloseHandle
pthread_mutex_destroy
mutex_destroy
死锁主要发生在有多个依赖锁存在时, 会在一个线程试图以与另一个线程相反顺序锁住互斥量时发生. 如何避免死锁是使用互斥量应该格外注意的东西。
总体来讲, 有几个不成文的基本原则:
对共享资源操作前一定要获得锁。
完成操作以后一定要释放锁。
尽量短时间地占用锁。
如果有多锁, 如获得顺序是ABC连环扣, 释放顺序也应该是ABC。
线程错误返回时应该释放它所获得的锁。
也许还有读者好奇,“挂起等待”和“唤醒等待线程”的操作如何实现?每个Mutex有一个等待队列,一个线程要在Mutex上挂起等待,首先在把自己加入等待队列中,然后置线程状态为睡眠,然后调用调度器函数切换到别的线程。一个线程要唤醒等待队列中的其它线程,只需从等待队列中取出一项,把它的状态从睡眠改为就绪,加入就绪队列,那么下次调度器函数执行时就有可能切换到被唤醒的线程。
一般情况下,如果同一个线程先后两次调用lock,在第二次调用时,由于锁已经被占用,该线程会挂起等待别的线程释放锁,然而锁正是被自己占用着的,该线程又被挂起而没有机会释放锁,因此就永远处于挂起等待状态了,这叫做死锁(Deadlock)。另一种典型的死锁情形是这样:线程A获得了锁1,线程B获得了锁2,这时线程A调用lock试图获得锁2,结果是需要挂起等待线程B释放锁2,而这时线程B也调用lock试图获得锁1,结果是需要挂起等待线程A释放锁1,于是线程A和B都永远处于挂起状态了。不难想象,如果涉及到更多的线程和更多的锁,有没有可能死锁的问题将会变得复杂和难以判断。
信号量
信号量(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 |
“windows中信号量和互斥量的区别是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/77274.html