除了互斥锁以及条件变量,还有信号量可以来进行线程同步。信号量从本质上讲是一个非负证书计数器,通常用来控制对公共资源的访问。
相关函数(头文件 #include <semaphore.h>):
int sem_init(sem_t *sem, int pshared, unsigned value)
int sem_post(sem_t *sem)
int sem_wait(sem_t *sem)
int sem_trywait(sem_t *sem)
int sem_destroy(sem_t *sem)
当可用的公共资源增加时,调用函数sem_post()来增加信号量。只有当信号量值大于0时,函数sem_wait()才能返回,并将信号量值减1,当信号量等于0时,sem_wait()将被阻塞直到信号量的值大于0。函数sem_trywait()是sem_wait()的非阻塞版本。(当信号量从0变为1时,会唤醒一个阻塞线程,其选择机制是由线程调度策略决定的)。
对于sem_init()函数:参数一为指向信号量结构的指针,参数二若不为0则表示在该信号量进程间共享,参数三表示信号量的初始值。
程序一:线程1打印0~9之间不能被3整除的整数,线程2打印0~9之间能被3整除的数。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <pthread.h> #include <semaphore.h> int i; sem_t sem1; void thread1() { for(i=0; i<9; i++) { if(i%3 == 0) { sem_post(&sem1); //增加信号量的值 } else { printf("thread1 print i : %d\n", i); } sleep(1); } sem_post(&sem1); pthread_exit(NULL); } void thread2() { while(i<9) { if(i%3 == 0) { sem_wait(&sem1); printf("thread2 print i : %d\n", i); } } pthread_exit(NULL); } int main() { pthread_t tid1, tid2; int ret; sem_init(&sem1, 0, 0); ret = pthread_create(&tid1, NULL, (void *)thread1, NULL); if(ret != 0) { perror("pthread_create"); exit(1); } ret = pthread_create(&tid2, NULL, (void *)thread2, NULL); if(ret != 0) { perror("pthread_create"); exit(1); } pthread_join(tid1, NULL); pthread_join(tid2, NULL); sem_destroy(&sem1); return 0; }执行结果:
程序二:线程1,2,3,要求线程执行的顺序为3,2,1.
#include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <semaphore.h> sem_t sem1; sem_t sem2; void *thread1() { sem_wait(&sem1); printf("This is thread 1\n"); } void *thread2() { sem_wait(&sem2); printf("This is thread 2\n"); sem_post(&sem1); } void *thread3() { printf("This is thread 3\n"); sem_post(&sem2); } int main() { pthread_t tid1, tid2, tid3; int ret; sem_init(&sem1, 0, 0); sem_init(&sem2, 0, 0); ret = pthread_create(&tid1, NULL, thread1, NULL); if(ret != 0) { perror("pthread_create"); exit(1); } ret = pthread_create(&tid2, NULL, thread2, NULL); if(ret != 0) { perror("pthread_create"); exit(1); } ret = pthread_create(&tid3, NULL, thread3, NULL); if(ret != 0) { perror("pthread_create"); exit(1); } pthread_join(tid1, NULL); pthread_join(tid2, NULL); pthread_join(tid3, NULL); return 0; }执行结果: