书接上文,我们讲了线程的高阶讲解,线程的控制,互斥与同步中的互斥,那么本文将为大家讲解线程的控制同步这一项,在讲解之前先为大家讲述一下,互斥与同步的区别
- 互斥:当某进程进行到某一阶段执行某一段代码时候,其他线程不能运行他们中的某一片段(临界资源的排他性访问)。
- 同步:要按照一定的先后顺序进行线程的顺序进行操作。
都是为了解决临界资源的竞争问题而设置的,那么具体的区别就是互斥没有顺序的控制而同步有了顺序的控制
互斥在作用上包含同步
那么下文将为大家二进行同步的实现(信号量)的介绍
信号量的分类:
- 无名信号量:线程间通信
- 有名信号链:进程间通信
本文为线程的进阶介绍,所以将为大家进行无名信号量的实现
框架:信号量的定义-->信号量的初始化-->信号量的pv操作-->信号量销毁
1.信号量的定义
sem_t sem;
- 功能:定义一个信号量类型的信号量变量(普遍为全局变量)
2.信号量的初始化
sem_init
int sem_init(sem_t *sem, int pshared, unsigned int value);
- 功能:将已经定义好的信号量赋值。
- 参数:
- sem 要初始化的信号量
- pshared
- 0 ;表示线程间使用信号量
- !=0 ;表示进程间使用信号量
- value 信号量的初始值,一般无名信号量
- 0 表示红灯,进程暂停阻塞
- 1 表示绿灯,进程可以通过执行
- 返回值:
- 成功 0
- 失败 -1
3.信号量的pv操作
- p-->申请资源-->申请一个信号量
- v-->释放资源-->释放一个信号量
sem_wait
int sem_wait(sem_t *sem);
- 功能:判断当前sem信号量是否有资源可用。(如果sem有资源(==1),则申请该资源,程序继续运行,如果sem没有资源(==0),则线程阻塞等待,一旦有资源则自动申请资源并继续运行程序,sem 申请资源后会自动执行 sem = sem - 1)
- 参数:sem 要判断的信号量资源
- 返回值:
- 成功 0
- 失败 -1
sem_post
int sem_post(sem_t *sem);
- 功能:函数可以将指定的sem信号量资源释放,并默认执行,sem = sem+1 ( 线程在该函数上不会阻塞)
- 参数:sem 要释放资源的信号量
- 返回值:
- 成功 0
- 失败 -1
4.信号量的销毁
sem_destroy
int sem_destroy(sem_t *sem);
- 功能:使用完毕将指定的信号量销毁
- 参数:sem要销毁的信号量
- 返回值:
- 成功 0
- 失败 -1
代码示例:
sem_t sem_a; sem_t sem_b; sem_t sem_c; void *pri_A(void *arg) { while(1) { sem_wait(&sem_a); printf("A\n"); sleep(1); sem_post(&sem_b); } } void *pri_B(void *arg) { while(1) { sem_wait(&sem_b); printf("B\n"); sleep(1); sem_post(&sem_c); } } void *pri_C(void *arg) { while(1) { sem_wait(&sem_c); printf("C\n"); sleep(1); sem_post(&sem_a); } } int main(int argc, const char *argv[]) { pthread_t tid[3]; pthread_create(&tid[0], NULL, pri_A, NULL); pthread_create(&tid[1], NULL, pri_B, NULL); pthread_create(&tid[2], NULL, pri_C, NULL); sem_init(&sem_a, 0, 1); sem_init(&sem_b, 0, 0); sem_init(&sem_c, 0, 0); pthread_join(tid[0], NULL); pthread_join(tid[1], NULL); pthread_join(tid[2], NULL); sem_destroy(&sem_a); sem_destroy(&sem_b); sem_destroy(&sem_c); return 0; }
如上可见,我们在线程中运用了同步就会产生我们想要的顺序的线程函数的进行
以上的内容就是线程的同步应用,通过信号量的处理,可以更好的解决面对临界资源竞争以及希望子线程的按照想要的顺序进行的问题,如有问题和疑问希望大家评论区指正,谢谢大家!