信号量是一种用于提供不一样进程或统一进程间不一样线程同步手段的原语,其操做包括P操做(将信号量的值-1)和V操做(将信号量值+1),其典型应用场景为多个生成者和多个消费者的状况,也用于控制多个进程的并发数。POSIX信号量包含两种类型:安全
a) POSIX有名信号量:使用PosixIPC名字标识并发
相关函数:函数
头文件 #include<semaphore.h>post
建立:sem_t*sem_open(const char *name, into flag, /mode_t mode, unsigned int value */);优化
成功返回指向信号量的指针,若出错则为SEM_FAILED(注意不为-1);value用于指定信号量的初始值,但该值不超过SEM_VALUE_MAX ;其他用法同mq_open线程
关闭:int sem_close(sem_t*sem); //成功返回0,若出错则为-1指针
关闭一个信号量并无将它从系统中删除,即POSIX有名信号量至少具备随内核的持续性,即便当前没有进程打开着某个信号量,它的值仍然保持。进程
删除:int sem_unlink(constchar *name); //若成功则为0,若出错则为-1内存
等待(P操做):int sem_wait(sem_t *sem); //阻塞形式,成功返回0,失败为-1;若被信号中断,错误码为EINTRget
intsem_trywait(sem_t *sem); //非阻塞形式,成功返回0,失败为-1;当没法当即获取信号量时返回EAGAIN错误
挂出(V操做):int sem_post(sem_t *sem); //成功返回0,失败-1
取值:intsem_getvalue(sem_t *sem, int *valp); //成功返回0,失败-1;成功则信号量的值存放与valp指向的变量中,若该信号量当前已上锁,则*valp为0或者负数,负数表示等待该信号量解锁的进程数为-*valp。有些平台上的实现是信号量*valp不会为负值。
p.s:在内核中,建立信号量的默认路径是/dev/shm,因此以/tmp/semname建立信号量会出错,解决办法是以semname做为参数建立信号量,将建立/dev/shm/sem.semname文件
b) POSIX基于内存的信号量:存放在内存中或共享内存中(存放在非共享内存中的只能用于线程同步)
相关函数:
建立和初始化信号量:intsem_init(sem_t *sem, int shared, unsigned int value);
sem参数执行应用程序必须分配的sem_t变量,若是shared 为0,那么待初始化的信号量是同一进程间各线程共享的,不然该信号量是在进程间共享的。当shared为非零时,该信号量必须存在某种类型的共享内存中,而要使用它的各个进程都须要能访问该共享内存。
返回值:失败返回-1,成功返回0
摧毁信号量:int sem_destroy(sem_t*sem); //失败返回-1,成功返回0
有名信号量和无名信号量二者的几点区别:
一、 有名信号量具备随内核的持续性,而无名信号量至少具备随进程的持续性,然而其真正的持续性却取决于存放信号量的内存区的类型,只有含有某个基于内存信号量的内存区保持有效,该信号量就一直存在。
二、 因为上述的区别也致使了删除有名信号量用sem_unlink(相似删除文件unlink),摧毁无名信号量用sem_destroy(有点至关于sem_close+sem_unlink;若不调用则随进程或共享内存区结束)
三、 其他的挂出、等待和取值操做一致
最后,总结一下信号量与互斥量,条件变量的差别:
1) 互斥锁老是由给它上锁的线程解锁,信号量的挂出却没必要由执行过它的等待操做的同一线程执行
2) 互斥锁要么被锁住,要么被解开(相似于二值信号量)
3) 信号量的挂出(post——+1)操做老是被记住,反映在信号量的值上;然而当向一个条件变量发送信号时,若是没有线程等待在该条件变量上,那么信号将丢失
4) 互斥量和条件变量多用于线程同步,但也可用于进程间;信号量的意图在于进程间同步,但也可用于线程间。
5) 在各类同步技巧中(互斥量+条件变量、读写锁、信号量),可以从信号处理程序中安全调用的惟一函数是sem_post
6) 互斥锁是为上锁而优化的,条件变量是为等待而优化的,信号量既可用于上锁也可用于等待,于是可能致使更多的开销和更高的复杂性;使用时结合实际