线程间通信-同步信号量(灯)

(一)信号灯简介
(1)线程同步是指多个任务按照约定的先后顺序相互配合完成一件事情。
eg:生产者(P + )和消费者(V - )的需要约定执行操作的先后顺序:
比如制造生产汽车,在整车还未完全生产完成,消费者拿到的产品是有问题的。因此消费者必须得等待生产者把正常生产完成后,才能消费者正常的消费使用。

(2)1968年,Edsgar Dijkstra基于信号量的概念提出了一种同步机制:由信号量(灯)的值 通过PV操作来决定线程是继续运行还是阻塞等待。
(3)信号量代表某一类资源的统称,其值表示系统中该资源的数量。信号量是一个受保护的变量,只能通过三种操作来访问:

		初始化:sem_init
		P操作(申请资源):sem_wait  自动对信号数量 减1
		V操作(释放资源):sem_post 自动对信号数量 加1

(二)Posix信号量
linux下遵循posix标准定义了两类信号量:

		无名信号量(基于内存的信号量)
		有名信号量

(三)semaphore库常用的信号量函数

头文件:#include <semaphore.h>
	
	    int sem_init(sem_t *sem, int pshared, unsigned int value);//初始化
	    int sem_wait(sem_t *sem);//P操作
	    int sem_post(sem_t *sem);//V操作

(1)sem:sem是要操作的信号量对象
(2)pshared:
0 表示线程间的信号量
1 表示进程间的信号量

(3 value:value就是信号量的个数。
(4)成功返回 0
失败返回 EOF

(四)注意事项
1)线程里面不可以写exit,否则整个进程都退出。
2)main函数退出,整个程序就退出,线程不存在。
3)线程的函数如果执行完毕,线程不存在,但是之前占用的资源还是存在的,因此也需要回收。
4) 不同的线程TID要区别开。

程序(一):利用两个信号量完成对共享内存的读和写

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 #include <pthread.h>
  4 #include <semaphore.h>
  5 #include <string.h>
  6 
  7 #define NUM 128
  8 
  9 char sharemem[NUM]; 
 10 sem_t sem_rd;             //定义的两个读和写信号量                                                                                                                                          
 11 sem_t sem_wr;
 12 
 13 void * read_pthread(void * arg);
 14 void * write_pthread(void * arg);
 15 
 16 int main(int argc, const char *argv[])
 17 {
 18     pthread_t read_tid;
 19     pthread_t write_tid;
 20 
 21     pthread_create(&read_tid, NULL, read_pthread, NULL);
 22     pthread_create(&write_tid, NULL, write_pthread, NULL);
 23 
 24     sem_init(&sem_rd, 0, 0);
 25     sem_init(&sem_wr, 0, 1);
 26 
 27 
 28     while(1)
 29     {
 30         sleep(1);
 31     }
 32     return 0;
 33 }
 34 
 35 void * write_pthread(void * arg)
 36 {
 37     char buf[20] = "";
38 
 39     pthread_detach(pthread_self());
 40     while(1)
 41     {                                                                                                                                                               
 42         sem_wait(&sem_wr);
 43         fgets(buf, 20, stdin);
 44         memset(sharemem, 0, NUM);
 45         memcpy(sharemem, buf, strlen(buf));//注意此时不能用sizeof(buf),因为始终sizeof是固定值,strlen才是得到字符串的长度。
 46         sem_post(&sem_rd);
 47     }
 48 }
 49 
 50 void * read_pthread(void * arg)
 51 {
 52     pthread_detach(pthread_self());
 53     while(1)
 54     {
 55         sem_wait(&sem_rd);
 56         printf("%s\n", sharemem);
 57         sem_post(&sem_wr);
 58     }
 59 }

程序(二):优化利用一个信号量进程读和写操作
或者在一个线程执行的前面加usleep(1000)延迟一下;

		sem_init(&sem, 0, 0);
 35 void * write_pthread(void * arg)
 36 {
 37     char buf[20] = "";
38 
 39     pthread_detach(pthread_self());
 40     while(1)
 41     {                                                                                                                                                               

 43         fgets(buf, 20, stdin);
 44         memset(sharemem, 0, NUM);
 45         memcpy(sharemem, buf, strlen(buf));//注意此时不能用sizeof(buf),因为始终sizeof是固定值,strlen才是得到字符串的长度。
 46         sem_post(&sem);
 47     }
 48 }
 49 
 50 void * read_pthread(void * arg)
 51 {
 52     pthread_detach(pthread_self());
 53     while(1)
 54     {
 55         sem_wait(&sem);
 56         printf("%s\n", sharemem);
 57       
 58     }
 59 }
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值