线程的同步、互斥机制

来源:互联网 发布:vivo手机怎么开4g网络 编辑:程序博客网 时间:2024/05/22 11:38

整理线程同步的API函数及其作用

线程同步的方式和机制

临界区、互斥量、事件、信号量四种方式

临界区(Critical Section)、互斥量(Mutex)、信号量(Semaphore)、事件(Event)的区别

1、临界区:通过对多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问。在任意时刻只允许一个线程对共享资源进行访问,如果有多个线程试图访问公共资源,那么在有一个线程进入后,其他试图访问公共资源的线程将被挂起,并一直等到进入临界区的线程离开,临界区在被释放后,其他线程才可以抢占。

2、互斥量:采用互斥对象机制。 只有拥有互斥对象的线程才有访问公共资源的权限,因为互斥对象只有一个,所以能保证公共资源不会同时被多个线程访问。互斥不仅能实现同一应用程序的公共资源安全共享,还能实现不同应用程序的公共资源安全共享

3、信号量:它允许多个线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目

4、事 件: 通过通知操作的方式来保持线程的同步,还可以方便实现对多个线程的优先级比较的操作。

API函数见上一节。

 注意点:能够运用同步机制实现生产者和消费者例程

producer.c

/*producer.c*/#include"shm_com.h"#include"sem_com.h"#include<signal.h>int ignore_signal(void){ /*忽略一些信号,以免非法突出程序*/signal(SIGINT,SIG_IGN);signal(SIGSTOP,SIG_IGN);signal(SIGQUIT,SIG_IGN);return 0;}int main(){char *shared_memory;struct shm_buff *shm_buff_inst;char buffer[BUFSIZ];int shmid,semid;/*定义信号量,用于实现访问共享内存的进程间的互斥*/ignore_signal();  /*用于防止程序非正常退出*/semid=semget(ftok(".",'a'),1,0666|IPC_CREAT);/*创建一个信号量*/init_sem(semid,1); /*初始值为1*//*创建共享内存*/shmid=shmget(ftok(".",'c'),sizeof(struct shm_buff),0666|IPC_CREAT);if(shmid==-1){perror("shmget failed");del_sem(semid);exit(1);}/*将共享内存地址映射到当前进程地址空间*/shared_memory=shmat(shmid,0,0);if(shared_memory==(void*)-1){perror("shmat");del_sem(semid);exit(1);}printf("Memory attached at %p\n",shared_memory);/*获取共享内存的映射地址*/shm_buff_inst=(struct shm_buff *)shared_memory;do{sem_p(semid);printf("Emter some text to the shared memory(enter 'quit' to exit):");/*向共享内存写入数据*/if(fgets(shm_buff_inst->buffer,SHM_BUFF_SZ,stdin)==NULL){perror("fgets");sem_v(semid);break;}shm_buff_inst->pid=getpid();sem_v(semid);}while(strncmp(shm_buff_inst->buffer,"quit",4)!=0);/*删除信号量*/del_sem(semid);/*删除共享内存到当前进程地址空间中的映射*/if(shmdt(shared_memory)==-1){perror("shmdt");exit(1);}exit(0);}
customer.c

/* customer.c */#include"shm_com.h"#include"sem_com.h"int main(){char *shared_memory=NULL;struct shm_buff *shm_buff_inst;int shmid,semid;/*获得信号量*/semid=semget(ftok(".",'a'),1,0666);if(semid==-1){perror("Producer isn't exist");exit(1);}/*获得共享内存*/shmid=shmget(ftok(".",'c'),sizeof(struct shm_buff),0666|IPC_CREAT);if(shmid==-1){perror("shmget");exit(1);}/*将共享内存地址映射到当前进程地址空间*/shared_memory=shmat(shmid,0,0);if(shared_memory==(void *)-1){perror("shmat");exit(1);}printf("Memory attached at %p\n",shared_memory);/*获得共享内存的映射地址*/shm_buff_inst=(struct shm_buff *)shared_memory;do{sem_p(semid);printf("Shared memory was written by process %d : %s",shm_buff_inst->pid,shm_buff_inst->buffer);if(strncmp(shm_buff_inst->buffer,"quit",4)==0){perror("strncmp");exit(1);}shm_buff_inst->pid=0;memset(shm_buff_inst->buffer,0,SHM_BUFF_SZ);sem_v(semid);}while(1);/*删除共享内存到当前进程地址空间中的映射*/if(shmdt(shared_memory)==-1){perror("shmdt");exit(1);}/*删除共享内存*/if(shmctl(shmid,IPC_RMID,NULL)==-1){perror("shmctl");exit(1);}exit(0);}

sem_com.c

/*sem_com.c*/#include"sem_com.h"/*信号量初始化(赋值)函数*/int init_sem(int sem_id,int init_value){union semun sem_union;sem_union.val=init_value;  /*init_value为初始值*/if(semctl(sem_id,0,SETVAL,sem_union)==-1){perror("Initialize semaphore");return -1;}return 0;}/*从系统中删除信号量的函数*/int del_sem(int sem_id){union semun sem_union;if(semctl(sem_id,0,IPC_RMID,sem_union)==-1){perror("Delete semaphore");return -1;}}/*p操作函数*/int sem_p(int sem_id){struct sembuf sem_b;sem_b.sem_num=0;  /*单个信号量的编号应该为0*/sem_b.sem_op=-1;  /*取值为-1,表示p操作*/sem_b.sem_flg=SEM_UNDO; /*系统自动释放将会在系统中残留的信号量*/if(semop(sem_id,&sem_b,1)==-1){perror("P operationn");return -1;}return 0;}/*V操作函数*/int sem_v(int sem_id){struct sembuf sem_b;sem_b.sem_num=0;  /*单个信号量的编号应该为0*/sem_b.sem_op=1;  /*取值为+1,表示v操作*/sem_b.sem_flg=SEM_UNDO; /*系统自动释放将会在系统中残留的信号量*/if(semop(sem_id,&sem_b,1)==-1){perror("V operationn");return -1;}return 0;}
sem_com.h

/*sem_com.h*/#include<sys/types.h>#include<sys/ipc.h>#include<sys/sem.h>#include<stdio.h>#include<stdlib.h>union semun{int val;struct semid_ds *buf;unsigned short *array;};/*信号量初始化(赋值)函数*/int init_sem(int sem_id,int init_value);/*从系统中删除信号量的函数*/int del_sem(int sem_id);/*p操作函数*/int sem_p(int sem_id);/*V操作函数*/int sem_v(int sem_id);
shm_com.h

/*shm_com.h*/#include<unistd.h>#include<stdlib.h>#include<stdio.h>#include<string.h>#include<sys/types.h>#include<sys/ipc.h>#include<sys/shm.h>#define SHM_BUFF_SZ  2048struct shm_buff{int pid;char buffer[SHM_BUFF_SZ];};

运行结果:






0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 买了学生票学生证丢了怎么办 取票学生证没带怎么办 学生卡的失磁怎么办 学生证没有充磁买不了学生票怎么办 买学生票不在优惠区间怎么办 火车票学生优惠次数用完怎么办 学生乘火车优惠磁卡丢了怎么办 磁卡锁的卡丢了怎么办 电梯磁卡扣丢了怎么办 买火车票手机号填错了怎么办 买火车票乘客身份核验失败怎么办 火车票不在一个车厢怎么办站票 坐火车丢东西了怎么办 g2坐过站了怎么办 坐火车买近了怎么办 打印的纸质火车票丢失怎么办 格力空调没保修单怎么办 格力空调不兑现保修怎么办 哈空调如果退市怎么办 空调保修单丢了怎么办 海尔空调发票丢了怎么办 格力空调发票丢了怎么办 联程航班第一程延误怎么办 飞机经停10小时怎么办 去车站买票没带身份证怎么办 转机航班第一班延误了怎么办 转机航班第一班取消了怎么办 香港转机大陆行李托运怎么办 联程车票第一班车晚点怎么办 到了普吉机场接机怎么办 被骚扰电话打个不停怎么办 网贷不停发信息怎么办 网贷天天发信息怎么办 诈骗电话一直打个不停怎么办 寄快递电话号码写错了怎么办 寄快递收件人号码错了怎么办 嫒和媛分不清楚怎么办 快递柜单号没了怎么办 邮政蜜蜂箱 退件怎么办 手机狂收验证码怎么办 快递柜超过24小时怎么办