linux 信号量和互斥锁,同样可以实现互斥,互斥锁和信号量有什么区别?

援引CU上一篇帖子的内容:

“信号量用在多线程多任务同步的,一个线程完成了某一个动作就通过信号量告诉别的线程,别的线程再进行某些动作(大家都在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.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值