声明:侵删
文章目录
- 1. 线程和进程的区别
- 2.prhread线程库相关API
- 3.线程间的同步和互斥
- 4.互斥锁
- 5.互斥锁例程
- 6.POISX信号量 [System V 信号量参考此文](https://blog.csdn.net/qq_43921241/article/details/103123667)
- 7.POSIX信号量例程
1. 线程和进程的区别
进程 :每个进程有自己独立的地址空间
Linux为每个进程创建task_struct (任务结构体,存放进程属性)
每个进程都参与内核调度,不影响其他进程
线程:进程在切换时系统开销大
很多操作系统引入了轻量级进程LWP(线程)
同一进程中的线程共享相同地址空间
Linux不区分进程、线程(Linux都认为成一个任务)
一个进程中的多个线程共享一下资源
线程ID
PC和相关寄存器
堆栈
errno
优先级
执行状态和属性
2.prhread线程库相关API
编译时候要注意链接pthread线程库
线程创建函数:pthread_creat
线程回收函数: pthread_join
线程退出函数:pthread_exit
3.线程间的同步和互斥
线程共享进程的空间地址和资源,对这些资源进行操作是必须注意线程间的同步和互斥。本文主要介绍POSIX的两种互斥机制: 信号量和互斥锁。
互斥锁适用于同时可用资源唯一的情况,信号量适合于同时可用资源为多个的情况。
4.互斥锁
互斥锁是一种以简单的加锁方式对共享资源的原子操作。互斥锁有两种状态:上锁和解锁。在同一时刻只有一个线程可以掌握互斥锁,拥有上锁状态的线程可以对共享资源进行操作,其余线程想要抢锁就会挂起直到拥有锁的进程释放锁。
互斥锁可以分为快速互斥锁、递归互斥锁、检错互斥锁。
快速锁:调用线程必须堵塞到拥有锁的进程释放锁为止
递归锁:递归锁能够成功的返回,并能增加调用线程在互斥上加锁的次数
检错锁:相当于非堵塞版的快速锁,抢不到锁不会堵塞会返回一个错误信息。
默认是快速互斥锁。
使用互斥锁之前必须初始化锁的类型。
互斥锁相关API
互斥锁初始化函数 pthread_mutex_init
互斥锁控制函数:上锁、解锁、检查锁、删除锁、
5.互斥锁例程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66/*mutex.c*/ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> #define THREAD_NUM 3 /*线程数*/ #define TASKK_NUM 3 /*每个线程执行的小任务数*/ #define DELAY_TIME 10 /*每个小任务最大时间间隔*/ pthread_mutex_t mutex; /*定义互斥锁*/ /*线程函数*/ void * func_thread(void *arg) { int thread_num = (int) arg; int delay_time = 0; int count = 0; if (pthread_mutex_lock(&mutex) == -1)/*抢锁*/ { perror("pthread_mutex_lock"); pthread_exit(NULL); } printf("The thread [%d] is beginningn",thread_num); for(count = 0; count<TASKK_NUM;count++) { delay_time =(int)(rand()%DELAY_TIME)+1; /*产生随机数1-DLY_TIME*/ sleep(delay_time); printf("tthread[%d],job[%d],sleep[%d]sn",thread_num,count,delay_time); } printf("pthread[%d] endn",thread_num); pthread_mutex_unlock(&mutex);/*解锁*/ pthread_exit(NULL); } int main() { pthread_t tid[THREAD_NUM]; int thread_num =0 ; srand((time(NULL))); /*初始化随机数种子*/ pthread_mutex_init(&mutex,NULL);/*初始化互斥锁为快速互斥锁*/ /*创建线程*/ for( thread_num=0;thread_num < THREAD_NUM;thread_num ++) { if (pthread_create(&tid[thread_num],NULL,func_thread,(void *) thread_num) != 0) { printf("Create pthread[%d] failedn",thread_num); exit(-1); } } printf("Creat all thread sucessed,please waitting ...n" ); /*回收进程*/ for(thread_num = 0;thread_num <THREAD_NUM;thread_num++) { pthread_join(tid[thread_num],NULL); printf("thread[%d] joinedn",thread_num); } pthread_mutex_destroy(&mutex); /*删除锁*/ exit(1); }
结果对比
6.POISX信号量 System V 信号量参考此文
信号量实质是一个非负整数的计数器,是操作系统中的PV原语,常用于线程间的同步与互斥。
一次 P 操作使信号量sem 减 1, 而一次 V 操作使 sem 加 1。 进程( 线程) 根据信号量的值来判断是否对公共资源具有访问权限。当 sem 的值大于等于 0 时,该进程(或线程)具有公共资源的访问权限;相反,当 sem 的值小于 0 时,该进程(线程)就将阻塞直到 sem 的值大于等于 0 为止。
信号量常用语进程(线程)之间的同步或者互斥
互斥 当信号量作互斥作用时,往往设置一个信号量来决定资源归属
同步信号量做同步机制时,往往设置多个信号量,通过初始化值和PV操作来决定他们的运行顺序。
POSIX信号量相关API
信号量创建初始化函数 sem_init
信号量操作函数 PV操作、删除、获取信号量的值
**
7.POSIX信号量例程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> #include <string.h> #include <semaphore.h> #define THREAD_NUM 3 /*线程数*/ #define TASKK_NUM 3 /*每个线程执行的小任务数*/ #define DELAY_TIME 10 /*每个小任务最大时间间隔*/ sem_t sem[THREAD_NUM]; /*线程函数*/ void * func_thread(void *arg) { int thread_num = (int) arg; int delay_time = 0; int count = 0; /*每个线程首先进行P操作 ,判断有无资源*/ sem_wait(&sem[thread_num]); printf("The thread [%d] is beginningn",thread_num); for(count = 0; count<TASKK_NUM;count++) { delay_time =(int)(rand()%DELAY_TIME)+1; /*产生随机数1-DLY_TIME*/ sleep(delay_time); printf("tthread[%d],job[%d],sleep[%d]sn",thread_num,count,delay_time); } printf("pthread[%d] endn",thread_num); pthread_exit(NULL); } int main() { pthread_t tid[THREAD_NUM]; int thread_num =0 ; srand((time(NULL))); /*初始化随机数种子*/ /*创建线程*/ for( thread_num=0;thread_num < THREAD_NUM;thread_num ++) { sem_init(&sem[thread_num],0,0);/*将所有信号量初始化为0*/ if (pthread_create(&tid[thread_num],NULL,func_thread,(void *) thread_num) != 0) { printf("Create pthread[%d] failedn",thread_num); exit(-1); } } /*将最后创建的一个进程进行V操作, sem[THREAD_NUM-1]变为1,最后创建的进程先运行*/ sem_post(&sem[THREAD_NUM-1]); printf("Creat all thread sucessed,please waitting ...n" ); /*回收进程*/ for(thread_num = THREAD_NUM -1;thread_num >= 0;thread_num --) { pthread_join(tid[thread_num],NULL); printf("thread[%d] joinedn",thread_num); /*每回收一个线程就将下一个要运行线程解开,对上一个信号量V操作*/ sem_post(&sem[(thread_num+THREAD_NUM-1)%THREAD_NUM]); } /*删除信号量*/ for(thread_num = 0;thread_num <THREAD_NUM-1;thread_num++) { sem_destroy(&sem[thread_num]); } exit(1); }
结果
最后
以上就是追寻篮球最近收集整理的关于Linux系统编程之线程控制及线程间同步互斥机制:POSIX信号量和互斥锁的全部内容,更多相关Linux系统编程之线程控制及线程间同步互斥机制内容请搜索靠谱客的其他文章。
发表评论 取消回复