linux高编线程-------线程同步-互斥量
线程同步
互斥量:某一个资源可能在使用的过程中产生竞争和冲突。那么互斥量解决同一时刻只有线程对资源进行操作。限制的是代码。
/********************** *功能:销毁一个互斥量 *参数:mutex:类型为pthread_mutex_t类型的变量 *返回值:成功返回0,失败返回errno * *******************/ int pthread_mutex_destroy(pthread_mutex_t *mutex); /******************** *功能:动态创建互斥量:如果 变量位于一个结构体中,用动态初始化 *参数:mutex:互斥变量 * attr:属性 * *****************/ int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr); /****************** *静态初始化 *互斥量如果是一个变量的话可以用静态初始化 * **************/ pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; /****lock-unlock:创建一个临界区****/ /****lock:是非阻塞,lock是阻塞*****/ int pthread_mutex_lock(pthread_mutex_t *mutex); int pthread_mutex_trylock(pthread_mutex_t *mutex); int pthread_mutex_unlock(pthread_mutex_t *mutex);
/***************** *功能:保证线程只被执行一次 *参数:once_control:变量 * init_routine:线程函数入口地址 ****************/ int pthread_once(pthread_once_t *once_control,void (*init_routine)(void)); pthread_once_t once_control = PTHREAD_ONCE_INIT;
下面两个例子说明线程互斥的使用
/********* 功能:创建20个线程,每个线程的任务就是从文件中读取数据,加1后,写入文件 使用到的相关知识:线程的创建销毁以及线程的互斥(解决线程之间的进程问题) *********/ #include <stdio.h> #include <stdlib.h> #include <pthread.h> #define THRNUM 20 #define FNAME "/tmp/out" #define SIZE 1024 //创建互斥量 static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; //线程 static void *thr_add(void *p) { FILE *fp; char buf[SIZE]; //1.打开文件 fp = fopen(FNAME,"r+"); if(fp == NULL) { perror("fopen()"); exit(1); } //2.锁住将要执行的代码 pthread_mutex_lock(&mut); fgets(buf,SIZE,fp); rewind(fp); // sleep(1); fprintf(fp,"%d\n",atoi(buf)+1); fclose(fp); //3.解锁 pthread_mutex_unlock(&mut); //4.线程退出 pthread_exit(NULL); } int main() { int i,err; //1.创建THRNUM个线程 pthread_t tid[THRNUM]; for(i = 0; i < THRNUM ;i++) { err = pthread_create(tid+i,NULL,thr_add,NULL); if(err) { fprintf(stderr,"pthread_create():%s\n",strerror(err)); exit(1); } } //2.等待收尸 for(i = 0; i < THRNUM ;i++) pthread_join(tid[i],NULL); //3.销毁互斥量 pthread_mutex_destroy(&mut); exit(0); }
范例2:四个线程不断向终端输出abcd字符,用线程a解线程b的锁,b解c的锁依次类推
/******************* 功能:4个线程分别向终端按照次序输出abcd 使用的知识:线程互斥量 ********************/ #include <stdio.h> #include <stdlib.h> #include <pthread.h> #define THRNUM 4 //四个线程的线程互斥量 static pthread_mutex_t mut[THRNUM]; /*函数功能:返回下一个线程顺序*/ static int next(int a) { if(a+1 == THRNUM) return 0; return a+1; } //线程 static void *thr_func(void *p) { int n = (int)p; int ch = 'a' + n; while(1) { //1.锁住当前线程执行代码 pthread_mutex_lock(mut+n); write(1,&ch,1); //2.解锁下一个线程执行代码 pthread_mutex_unlock(mut+next(n)); } //3.线程退出 pthread_exit(NULL); } int main() { int i,err; pthread_t tid[THRNUM]; //1.创建线程并创建互斥量 for(i = 0; i < THRNUM ;i++) { pthread_mutex_init(mut+i,NULL); pthread_mutex_lock(mut+i); err = pthread_create(tid+i,NULL,thr_func,(void *)i); if(err) { fprintf(stderr,"pthread_create():%s\n",strerror(err)); exit(1); } } //2.解锁第一个线程互斥量 pthread_mutex_unlock(mut+0); //3.5s信号打断 alarm(5); //4.收尸 for(i = 0; i < THRNUM ;i++) { pthread_join(tid[i],NULL); } exit(0);
筛质数:
/****************** *功能:多线程筛质数 *知识点:互斥锁的使用 * **************/ #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <unistd.h> //质数范围 #define LEFT 30000000 #define RIGHT 30000200 //线程数量 #define THRNUM 4 //num > 0 有任务 //num = 0 无任务 //num = -1 完成 static int num = 0 ; //互斥量 static pthread_mutex_t mut_num = PTHREAD_MUTEX_INITIALIZER ; void *thr_primer(void *); int main() { int i,err; pthread_t tid[THRNUM]; //1.创建THRNUM个线程 for(i = 0; i <= THRNUM ;i++) { err = pthread_create(tid+(i),NULL,thr_primer,(void *)i); if(err) { fprintf(stderr,"pthread_create():%s\n",strerror(err)); exit(1); } } //2.main线程负责下发任务 // 每次查看num的值之前需要加锁 for(i = LEFT ; i <= RIGHT ; i++) { //2.1看num的值,需要加锁 pthread_mutex_lock(&mut_num); //2.2:num != 0 :说明任务还没有派发下去 while(num != 0) { //2.2.1等待,让线程有机会把数拿走 pthread_mutex_unlock(&mut_num); // 2.2.2出让调度器给别的线程 sched_yield(); //2.2.3其他线程抢锁后加锁+解锁,main线程需要抢锁继续下发任务 pthread_mutex_lock(&mut_num); } //2.3下发任务 num = i ; //2.4解锁 pthread_mutex_unlock(&mut_num); } //3.所有任务处理完毕:需要查看num值是否为0,所以加锁查看 pthread_mutex_lock(&mut_num); //3.1最后一个任务发出去后,但是其他线程没有处理完,main线程又抢到锁 while(num != 0) { //解锁 pthread_mutex_unlock(&mut_num); //出让调度器 sched_yield(); //抢锁 pthread_mutex_lock(&mut_num); } //4.所有任务处理完毕,解锁 num = -1 ; pthread_mutex_unlock(&mut_num); //5.收尸 for(i = LEFT; i <= THRNUM ;i++) pthread_join(tid[i],NULL); //6.销毁互斥量 pthread_mutex_destroy(&mut_num); exit(0); } //线程:需要注意临界区的跳转一定要解锁 void *thr_primer(void *p) { int i,j,mark; while(1) { //加锁看num的值 pthread_mutex_lock(&mut_num); //num = 0 解锁等待不为0 的时候 while(num == 0) { //为0 解锁等待 pthread_mutex_unlock(&mut_num); sched_yield(); //再抢锁看num的值 pthread_mutex_lock(&mut_num); } if(num == -1) { //没有任务的时候解锁并跳出循环 pthread_mutex_unlock(&mut_num); break ; } i = num ; num = 0 ; pthread_mutex_unlock(&mut_num); mark = 1; for(j = 2; j < i/2; j++) { if(i % j == 0) { mark = 0; break; } } if(mark) printf("[%d]%d is a primer.\n",(int)p,i); } pthread_exit(NULL); }