互斥锁、条件变量、信号量浅析

互斥锁、条件变量、信号量浅析

互斥锁与条件变量

  1. 条件变量是为了保证同步 条件变量用在多线程多任务同步的,一个线程完成了某一个动作就通过条件变量告诉别的线程,别的线程再进行某些动作(大家都在semtake的时候,就阻塞在哪里)。信号量可以看作是有计数的条件变量。
  2. 互斥锁是为了保证互斥 互斥锁是用在多线程多任务互斥的,一个线程占用了某一个资源,那么别的线程就无法访问,直到这个线程unlock,其他的线程才开始可以利用这个资源。比如对全局变量的访问,有时要加锁,操作完了,再解锁。互斥锁可以看作是二值信号量。
  3. 有的时候互斥锁和条件变量会同时使用的 条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足。在发送信号时,如果没有线程等待在该条件变量上,那么信号将丢失。

信号量

简介

信号量可以看作是互斥锁和条件变量的结合,而互斥锁和条件变量则可以看作是信号量的一种特殊形式

信号量:只要信号量的value大于0,其他线程就可以sem_wait成功,成功后信号量的value减一。若value值不大于0,则sem_wait阻塞,直到sem_post释放后value值加1。

以下是信号灯(量)的一些概念:

  1. 信号灯与互斥锁和条件变量的主要不同在于”灯”的概念,灯亮则意味着资源可用,灯灭则意味着不可用。如果说后两中同步方式侧重于**”等待”操作,即资源不可用的话,信号灯机制则侧重于"点灯"**,即告知资源可用;
  2. 没有等待线程的解锁或激发条件都是没有意义的,而没有等待灯亮的线程的点灯操作则有效,且能保持灯亮状态。
  3. 信号灯的应用除了灯亮/灯灭这种二元灯以外,也可以采用大于1的灯数,以表示资源数大于1,这时可以称之为多元灯。

信号灯(量)API

创建和注销

POSIX信号灯标准定义了有名信号灯和无名信号灯两种,但LinuxThreads的实现仅有无名灯,同时有名灯除了总是可用于多进程之间以外,在使用上与无名灯并没有很大的区别,因此下面仅就无名灯进行讨论。

  1. 创建

    int sem_init(sem_t *sem, int pshared, unsigned int value)

    这是创建信号灯的API,其中value为信号灯的初值,pshared表示是否为多进程共享而不仅仅是用于一个进程。LinuxThreads没有实现多进程共享信号灯,因此所有非0值的pshared输入都将使sem_init()返回-1,且置errnoENOSYS。初始化好的信号灯由sem变量表征,用于以下点灯、灭灯操作。

  2. int sem_destroy(sem_t * sem)

    被注销的信号灯sem要求已没有线程在等待该信号灯,否则返回-1,且置errnoEBUSY。除此之外,LinuxThreads的信号灯注销函数不做其他动作。

点灯和灭灯
  1. 点灯

    int sem_post(sem_t * sem)

    点灯操作将信号灯值原子地加1,表示增加一个可访问的资源,sem_post()是唯一能用于异步信号处理函数的POSIX异步信号安全的API。

  2. 灭灯

    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

获取灯值

int sem_getvalue(sem_t * sem, int * sval)

读取sem中的灯计数,存于*sval中,并返回0。

辨析拾遗

  1. 互斥锁必须是谁上锁就由谁来解锁,而信号量的wait和post操作不必由同一个线程执行。
  2. 互斥锁是为上锁而优化的;条件变量是为等待而优化的; 信号量既可用于上锁,也可用于等待,因此会有更多的开销和更高的复杂性。
  3. 互斥锁,条件变量都只用于同一个进程的各线程间,而信号量(有名信号量)可用于不同进程间的同步。当信号量用于进程间同步时,要求信号量建立在共享内存区。
  4. 信号量有计数值,每次信号量post操作都会被记录,而条件变量在发送信号时,如果没有线程在等待该条件变量,那么信号将丢失。

Ref:

http://blog.chinaunix.net/uid-20671208-id-4935154.html

http://blog.chinaunix.net/uid-23061624-id-79936.html

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值