Linux互斥量和信号量的区别以及适用场景

互斥量和信号量的区别

1.互斥量用于线程的互斥:

  • 互斥:加锁解锁,是指某一资源同时只允许一个访问者对其进行访问(比如原子操作一段代码或一个变量),具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序(这个需要同步来解决),即访问是无序的,释放了锁接下来谁能竞争到谁就去访问资源。

2.信号量用于线程的同步:

  • 同步:P–,V++操作,是指在互斥的基础上通过其它机制(比如原子操作一个计数器)实现访问者对资源的有序访问

在大多数情况下,同步已经实现了互斥(spin lock),特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源。

适用场景1(顺序性角度)

互斥量值只能为0/1信号量值可以为非负整数(当信号量初始值设置为1的时候,其实信号量就相当于互斥锁了)

  • 互斥量可以用在线程间无顺序无同步要求的场景,常用在保护邻接资源的正确访问; 比如票,顺序随机,只要保证共享的票数正确减少即可;

  • 信号量可以用在生产流水线,比如我们有ABC产品,生产完A才能生产B,生产完B才能生产C,我们就可以设置三个ABC信号量,代表他们剩余产品的个数,这样各线程之间生产的时候只需要P()--自己需要的前一个产品的信号量>=0即可生产,否则进入阻塞等待队列等V操作唤醒; 若成功生产一个之后V()++即可达到同步其他线程的目的,保证了一定顺序的同步性; 比反复加锁解锁更方便;

适用场景2(底层原理分析)

  • mutex加锁解锁,内核中一般用于对一段代码的保护; 进入内核态的切换等,如果锁的时间不长的话,开销太大,适合等待时间就的场景;
  • sem信号量,内核中一般用于对一个变量的保护; 底层是spin lock自旋锁,等待时间短的话比mutex效率更高,不过等待时间久的话,占用cpu一直自旋,也得不偿失;

C++11的atomic原子操作(锁CPU访问的系统总线原理),其实和linux的mutex用法差不多,都能达到访问临界资源的线程安全,只不过效率不同,一个陷入内核上锁,一个cpu访问总线的时候加锁;
同时:
bool类型的atomic 不就是mutex嘛~
unsigned int 类型的atomic 不就是sem信号量嘛~

猜你喜欢

转载自blog.csdn.net/wtl666_6/article/details/129699100