线程同步(互斥锁与信号量的作用与区别)
“信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作(大家都在semtake的时候,就阻塞在 哪里)。而互斥锁是用在多线程多任务互斥的,一个线程占用了某一个资源,那么别的线程就无法访问,直到这个线程unlock,其他的线程才开始可以利用这 个资源。比如对全局变量的访问,有时要加锁,操作完了,在解锁。有的时候锁和信号量会同时使用的”
也就是说,信号量不一定是锁定某一个资源,而是流程上的概念,比如:有A,B两个线程,B线程要等A线程完成某一任务以后再进行自己下面的步骤,这个任务 并不一定是锁定某一资源,还可以是进行一些计算或者数据处理之类。而线程互斥量则是“锁住某一资源”的概念,在锁定期间内,其他线程无法对被保护的数据进 行操作。在有些情况下两者可以互换。
两者之间的区别:
作用域
信号量: 进程间或线程间(linux仅线程间的无名信号量pthread semaphore)
互斥锁: 线程间
上锁时
信号量: 只要信号量的value大于0,其他线程就可以sem_wait成功,成功后信号量的value减一。若value值不大于0,则sem_wait使得线程阻塞,直到sem_post释放后value值加一,但是sem_wait返回之前还是会将此value值减一
互斥锁: 只要被锁住,其他任何线程都不可以访问被保护的资源
以下是信号灯(量)的一些概念:
信号灯与互斥锁和条件变量的主要不同在于”灯”的概念,灯亮则意味着资源可用,灯灭则意味着不可用。如果说后两中同步方式侧重于”等待”操作,即资 源不可用的话,信号灯机制则侧重于点灯,即告知资源可用;
没有等待线程的解锁或激发条件都是没有意义的,而没有等待灯亮的线程的点灯操作则有效,且能保持 灯亮状态。当然,这样的操作原语也意味着更多的开销。
信号灯的应用除了灯亮/灯灭这种二元灯以外,也可以采用大于1的灯数,以表示资源数大于1,这时可以称之为多元灯。
1. 创建和 注销
POSIX信号灯标准定义了有名信号灯和无名信号灯两种,但LinuxThreads的实现仅有无名灯,同时有名灯除了总是可用于多进程之间以外,在使用上与无名灯并没有很大的区别,因此下面仅就无名灯进行讨论。
int sem_init(sem_t *sem, int pshared, unsigned int value)
这是创建信号灯的API,其中value为信号灯的初值,pshared表示是否为多进程共享而不仅仅是用于一个进程。LinuxThreads没有实现 多进程共享信号灯,因此所有非0值的pshared输入都将使sem_init()返回-1,且置errno为ENOSYS。初始化好的信号灯由sem变 量表征,用于以下点灯、灭灯操作。
int sem_destroy(sem_t * sem)
被注销的信号灯sem要求已没有线程在等待该信号灯,否则返回-1,且置errno为EBUSY。除此之外,LinuxThreads的信号灯 注销函数不做其他动作。
sem_destroy destroys a semaphore object, freeing the resources it might hold. No threads should be waiting on the
semaphore at the time sem_destroy is called. In the LinuxThreads implementation, no resources are associated with
semaphore objects, thus sem_destroy actually does nothing except checking that no thread is waiting on the semaphore.
2. 点灯和灭灯
int sem_post(sem_t * sem)
点灯操作将信号灯值原子地加1,表示增加一个可访问的资源。
int sem_wait(sem_t * sem)
int sem_trywait(sem_t * sem)
sem_wait()为等待灯亮操作,等待灯亮(信号灯值大于0),然后将信号灯原子地减1,并返回。sem_trywait()为sem_wait()的非阻塞版,如果信号灯计数大于0,则原子地减1并返回0,否则立即返回-1,errno置为EAGAIN。
3. 获取灯值
int sem_getvalue(sem_t * sem, int * sval)
读取sem中的灯计数,存于*sval中,并返回0。
4. 其他
sem_wait()被实现为取消点。(取消点事什么意思???)
sem_wait is a cancellation point.
取消点的含义:
当用pthread_cancel()一个线程时,这个要求会被pending起来,当被cancel的线程走到下一个cancellation point时,线程才会被真正cancel掉。
而且在支持原子”比较且交换CAS”指令的体系结构上,sem_post()是唯一能用于异步信号处理函数的POSIX异步信号 安全的API。
On processors supporting atomic compare-and-swap (Intel 486, Pentium and later, Alpha, PowerPC, MIPS II, Motorola 68k),
the sem_post function is async-signal safe and can therefore be called from signal handlers. This is the only thread syn-
chronization function provided by POSIX threads that is async-signal safe.
On the Intel 386 and the Sparc, the current LinuxThreads implementation of sem_post is not async-signal safe by lack of
the required atomic operations.
互斥量(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。
- 创建 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. 互斥量的加锁和解锁必须由同一线程分别对应使用,信号量可以由一个线程释放,另一个线程得到。
线程同步(互斥锁与信号量的作用与区别)相关推荐
- java 信号量 互斥锁_线程同步(互斥锁与信号量的作用与区别)
"信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作(大家都在semtake的时候,就阻塞在 哪里).而互斥锁是用在多线程多任务互斥的,一 ...
- c++ linux 线程等待与唤醒_Linux线程同步(互斥量、信号量、条件变量、生产消费者模型)...
为什么要线程同步? 线程间有很多共享资源,都对一个共享数据读写操作,线程操作共享资源的先后顺序不确定,可能会造成数据的冲突 看一个例子 两个线程屏行对全局变量count++ (采用一个val值作为中间 ...
- 判断sem信号量为零_Linux线程同步(互斥量、信号量、条件变量、生产消费者模型)...
为什么要线程同步? 线程间有很多共享资源,都对一个共享数据读写操作,线程操作共享资源的先后顺序不确定,可能会造成数据的冲突 看一个例子 两个线程屏行对全局变量count++ (采用一个val值作为中间 ...
- 线程同步(互斥锁、条件、读写锁、信号量)
参考:(四十三)线程--线程同步(互斥锁.读写锁.条件变量.信号量) 作者:FadeFarAway 发布时间:2017-01-17 21:25:28 网址:https://blog.csdn.net/ ...
- Linux多线程开发-线程同步-互斥锁pthread_mutex_t
1.互斥锁 同一时刻只允许一个线程对临界区进行访问.POSIX库中用类型pthread_mutex_t来定义互斥锁,类型在pthreadtypes.h中定义. 2.如何声明一个互斥锁 #include ...
- c++ linux 线程等待与唤醒_C++ Linux线程同步机制:POSIX信号量,互斥锁,条件变量...
线程同步机制:POSIX 信号量,互斥量,条件变量 POSIX 信号量 常用的POSIX 信号量函数为如下5个: sem_init sem_destroy sem_wait sem_trywait s ...
- java 多线程(四)—— 线程同步/互斥=队列+锁
同步.异步.互斥的区别 在很多文章中,直接把同步缩小为互斥,并称之为同步.下面也是这样的. 一.线程同步 = 队列 + 锁 同步(这里说的其实是互斥)就是多个线程同时访问一个资源. 那么如何实现? 队 ...
- 线程安全: 互斥锁和自旋锁(10种)
无并发,不编程.提到多线程就很难绕开锁?. iOS开发中较常见的两类锁: 1. 互斥锁: 同一时刻只能有一个线程获得互斥锁,其余线程处于挂起状态. 2. 自旋锁: 当某个线程获得自旋锁后,别的线程会一 ...
- 自旋锁、互斥锁和信号量
自旋锁 Linux内核中最常见的锁是自旋锁(spin lock).自旋锁最多只能被一个可执行线程持有.如果一个执行线程试图获得一个已经被持有的自旋锁,那么该线程就会一直进行忙循环--旋转--等待锁重新 ...
- linux线程(互斥锁、条件)
线程概念: 典型的UNIX/Linux进程可以看成只有一个控制线程:一个进程在同一时刻只做一件事情.有了多个控制线程后,在程序设计时可以把进程设计成在同一时刻做不止一件事,每个线程各自处理独立的任务. ...
最新文章
- 人脸识别的“生意经”
- electron 开发环境搭建
- 常用API-3(System类、Math类、Arrays类、正则表达式)
- 【大数据】Hadoop入门预告版
- redis常用命令与特性
- 《数据结构》双链循环线性表
- 开源的Linphone SIP 电话存在栈漏洞,可远程使客户端设备崩溃
- 企业知识管理与协同软件Confluence搭建与配置
- excel表格打开是乱码怎么办?
- sql server数据库可疑状态解决方法
- 计算机行业未来的规划模板,计算机专业个人职业规划优秀模板
- C++课程设计任务书
- 程序员客栈 接不到单子_常见(但不常见)单子
- 微信小程序获取用户信息
- 小学四则运算练习软件需求说明
- C语言中的if、else if 的用法和区别
- tshark 使用说明
- 七日杀服务器怎么修改天数,七日杀调整游戏天数 | 手游网游页游攻略大全
- Machine Learning Approach to RF Transmitter Identification
- 【遇见Doris】Apache Doris 在京东广告平台的应用
热门文章
- 阶段3 2.Spring_10.Spring中事务控制_5 spring事务控制的代码准备
- vector 简单使用
- Linux笔记--Linux进程通信
- Maven运行时异常java.lang.UnsupportedClassVersionError的解决方案
- 文成小盆友python-num6 -反射 ,常用模块
- socket,ioctl获取ip
- 【转载】.NET系统学习----Assembly
- string成员函数
- 用Python实现BP神经网络(附代码)
- HDU 2899 :(二分求最小值)