c语言信号量使用心得体会

1、选用什么标准的信号量

在Linux中信号量有两种标准,一种是System V,另一种是Posix标准。其中System V是早期的标准;

Posix(Portable Operating System Interface )是一个由IEEE开发的一系列标准,它还是由ISO(国际标准化组织)和IEC(国际电工委员会)采纳的国际标准。而System v是Unix操作系统众多版本的一个分支。

实际使用中Posix标准封装地更好,使用更简单。一般线程间的同步使用Posix无名信号量比较方便。但是sem_wait成功后获取信号灯后,进程如果意外终止。

2、使用过程中常见问题汇总

(1)System V标准下获取信号量值的用法为val = semctl(semid, 0, GETVAL);

(2)semaphore信号量和互斥量的区别:semaphore信号量会将竞争的线程挂起,保证前一个线程从阻塞态释放后后一个线程能够被处理。而mutex则不保证这一点(可能一个线程恰好每次轮到它执行,而对资源独占或者分配不均的情况)。

(3)不同进程之间用有名信号量同步的时候,一般用共享内存将标识字符串存储起来。

3、信号量的缺点,什么时候使用信号量?

P操作原语:

(1) sem 减1

(2)若sem 大于等于0,线程继续执行.

(3)若sem < 0 ,线程进入阻塞队列.

V 操作原语:

(1)sem加1

(2)若sem 大于 0, 线程继续执行

(3)若sem 小于等于0,唤醒阻塞队例的线程

从中可以看到,执行V操作之后若sem小于等于0,则阻塞队列中阻塞的线程或进程个数为|sem|+1个;而阻塞线程或进程是存放在一个阻塞链表中的,会保证顺序依次被唤醒,这一特性就能实现大于3个数量的线程或进程实现互斥。但是由于阻塞会牵扯到睡眠,再唤醒需要线程或进程上下文切换,切换是非常耗费时间的。因此当信号量对被保护的资源占用的时间比线程或进程切换时间长很多的时候,可以选择应用信号量。

那如何减少上下文切换呢?

<既然上下文切换会导致额外的开销,因此减少上下文切换次数便可以提高多线程程序的运行效率。减少上下文切换的方法有无锁并发编程、CAS算法、使用最少线程和使用协程。

  • 无锁并发编程。多线程竞争时,会引起上下文切换,所以多线程处理数据时,可以用一些办法来避免使用锁,如将数据的ID按照Hash取模分段,不同的线程处理不同段的数据
  • CAS算法。Java的Atomic包使用CAS算法来更新数据,而不需要加锁
  • 使用最少线程。避免创建不需要的线程,比如任务很少,但是创建了很多线程来处理,这样会造成大量线程都处于等待状态
  • 协程。在单线程里实现多任务的调度,并在单线程里维持多个任务间的切换>(尖括号部分,引用自“https://www.cnblogs.com/signheart/p/3e3379943de1c36d5bcc7d8cee4b9825.html”,signheart立心)

而协程其本质是在一个线程里面去分时调用不同逻辑处理单元——协程。

协程暂停,和线程的阻塞是有本质区别的。协程的暂停完全由程序控制,线程的阻塞状态是由操作系统内核来进行切换。时序上确定的,不会产生时序上的不确定性。

据目前了解,协程应该还是顺序执行的,只是缩短了线程切换时间。在一个线程中如果很多个协程依然经常没有事情做,该线程应该还是会比较耗费资源。并且如果同一个线程中的协程,有些比较耗费时间,那么其它协程就得不到响应。

应用场景:

yield这个关键字就是用来产生中断, 并保存当前的上下文的, 比如说程序的一段代码是访问远程服务器,那这个时候CPU就是空闲的,就用yield让出CPU,接着执行下一段的代码,如果下一段代码还是访问除CPU以外的其它资源,还可以调用yield让出CPU. 继续往下执行,这样就可以用同步的方式写异步的代码了.

 

 

你可能感兴趣的:(c语言信号量)