除了互斥锁以及条件变量,还有信号量可以来进行线程同步。信号量从本质上讲是一个非负证书计数器,通常用来控制对公共资源的访问。
相关函数(头文件 #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;
}
执行结果:
thread2 print i : 0
thread1 print i : 1
thread1 print i : 2
thread2 print i : 3
thread1 print i : 4
thread1 print i : 5
thread2 print i : 6
thread1 print i : 7
thread1 print i : 8
thread2 print i : 9
程序二:线程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;
}
执行结果:
This is thread 3
This is thread 2
This is thread 1