sem信号量与死锁的边缘
1. 演示一个例子,出现死锁,用strace debug得到
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<string.h>
#include<semaphore.h> sem_t sem; typedef struct _cal_
{
int sum;
}CAL;
CAL cal; void *calculate(void*arg)
{
int i;
int sum;
for(i = 0; i < 100; i++)
{
cal.sum = cal.sum + i;
}
sem_post(&sem);
} void *sum(void *arg)
{
sem_wait(&sem);
printf("the sum is %d\n",cal.sum);
} void *times(void *arg)
{
sem_wait(&sem);
printf("the times is %d\n",cal.sum * cal.sum);
} int main(void)
{
int ret=-1;
pthread_t th[3];
sem_init(&sem,0,0);
ret = pthread_create(&th[0],NULL,calculate,NULL);
if (ret != 0)
{
printf("Pthread_create failed\n");
return -1;
} ret = pthread_create(&th[1],NULL,sum,NULL);
if (ret != 0)
{
printf("Pthread_create failed\n");
return -1;
} ret = pthread_create(&th[1],NULL,times,NULL);
if (ret != 0)
{
printf("Pthread_create failed\n");
return -1;
} pthread_join(th[0],NULL);
pthread_join(th[1],NULL);
pthread_join(th[2],NULL);
return 0;
}
mprotect(0xb5d46000, 4096, PROT_NONE) = 0
clone(child_stack=0xb6546464, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0xb6546ba8, {entry_number:6, base_addr:0xb6546b40, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}, child_tidptr=0xb6546ba8) = 17181
futex(0xb6546ba8, FUTEX_WAIT, 17181, NULL
futex(0xb7533ba8, FUTEX_WAIT, 17204, NULLthe times is 4950
) = 0
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV (core dumped) +++
Segmentation fault (core dumped)
上述的log表明,该code出现死锁,FUTEX_WAIT....... 而且Core Dumped 虽然times is 9801结果出来。(一开始测试不出来)
2. 基于信号量的问题,需要进行优化和解决:
更新一版代码:
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<string.h>
#include<semaphore.h> sem_t sem_cal;
sem_t sem_times; typedef struct _cal_
{
int sum;
}CAL;
CAL cal; void *calculate(void*arg)
{
int i;
int sum;
for(i = 0; i < 100; i++)
{
cal.sum = cal.sum + i;
}
sem_post(&sem_cal);
} void *sum(void *arg)
{
sem_wait(&sem_cal);
printf("the sum is %d\n",cal.sum);
sem_post(&sem_times);
} void *times(void *arg)
{
sem_wait(&sem_times);
printf("the times is %d\n",cal.sum * cal.sum);
} int main(void)
{
int ret=-1;
pthread_t th[3];
sem_init(&sem_cal,0,0);
sem_init(&sem_times,0,0);
ret = pthread_create(&th[0],NULL,calculate,NULL);
if (ret != 0)
{
printf("Pthread_create failed\n");
return -1;
} ret = pthread_create(&th[1],NULL,sum,NULL);
if (ret != 0)
{
printf("Pthread_create failed\n");
return -1;
} ret = pthread_create(&th[1],NULL,times,NULL);
if (ret != 0)
{
printf("Pthread_create failed\n");
return -1;
} pthread_join(th[0],NULL);
pthread_join(th[1],NULL);
pthread_join(th[2],NULL);
return 0;
}
但是出现:
the sum is 4950
the times is 24502500
Segmentation fault (core dumped)
futex(0xb65afba8, FUTEX_WAIT, 17277, NULL) = -1 EAGAIN (Resource temporarily unavailable)
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV (core dumped) +++
Segmentation fault (core dumped)
此时出现段错误,但是结果都正常。
Resource temporarily unavailable 表明资源冲突
3. 跟着解决这个段错误的问题:
原来是 ret = pthread_create(&th[1],NULL,times,NULL);同一个线程ID。
(DUANG)
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<string.h>
#include<semaphore.h> sem_t sem_cal;
sem_t sem_times; typedef struct _cal_
{
int sum;
}CAL;
CAL cal; void *calculate(void*arg)
{
int i;
int sum;
for(i = 0; i < 100; i++)
{
cal.sum = cal.sum + i;
}
sem_post(&sem_cal);
} void *sum(void *arg)
{
sem_wait(&sem_cal);
printf("the sum is %d\n",cal.sum);
sem_post(&sem_times);
} void *times(void *arg)
{
sem_wait(&sem_times);
printf("the times is %d\n",cal.sum * cal.sum);
} int main(void)
{
int ret=-1;
pthread_t th[3];
sem_init(&sem_cal,0,0);
sem_init(&sem_times,0,0);
ret = pthread_create(&th[0],NULL,calculate,NULL);
if (ret != 0)
{
printf("Pthread_create failed\n");
return -1;
} ret = pthread_create(&th[1],NULL,sum,NULL);
if (ret != 0)
{
printf("Pthread_create failed\n");
return -1;
} ret = pthread_create(&th[2],NULL,times,NULL);
if (ret != 0)
{
printf("Pthread_create failed\n");
return -1;
} pthread_join(th[0],NULL);
pthread_join(th[1],NULL);
pthread_join(th[2],NULL);
return 0;
}
该博客的目的是:
1. 通过多个信号量去完成业务。
2. 信号量和互斥锁的区别下节分析。
sem信号量与死锁的边缘的更多相关文章
- [并发编程 - 多线程:信号量、死锁与递归锁、时间Event、定时器Timer、线程队列、GIL锁]
[并发编程 - 多线程:信号量.死锁与递归锁.时间Event.定时器Timer.线程队列.GIL锁] 信号量 信号量Semaphore:管理一个内置的计数器 每当调用acquire()时内置计数器-1 ...
- C++多线程框架-----Mutex互斥和Sem信号量
互斥和信号量是多线程编程的两个基础,其原理就不详细说了,大家去看看操作系统的书或者网上查查吧. 对于互斥的实现,无论什么操作系统都离不开三个步骤 1.初始化互斥锁 2.锁操作 3.解锁操 ...
- JAVA通过信号量避免死锁
死锁是这样一种情形:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放.由于线程被无限期地阻塞,因此程序不可能正常终止. 导致死锁的根源在于不适当地运用"synchronized ...
- python基础--GIL全局解释器锁、Event事件、信号量、死锁、递归锁
ps:python解释器有很多种,最常见的就是C python解释器 GIL全局解释器锁: GIL本质上是一把互斥锁:将并发变成串行,牺牲效率保证了数据的安全 用来阻止同一个进程下的多个线程的同时执行 ...
- 利用多个sem信号量在线程通讯
直接上代码,主要用到sem_trywait & sem_post #include<stdio.h> #include<pthread.h> #include<s ...
- 信号量sem 的用法
#include <semaphore.h> sem_t sem; sem_init(&sem, 0, 0); sem_post(&sem); sem_wait(& ...
- linux 进程间信号量管理程序之sem_timedwait使用
在开发过程中,有三个独立执行的程序模块,三个模块都对sqlite数据库进行读写操作.sqlite在linux共享性较差,所以须要增加相互排斥信号量解决三个模块訪问数据库该问题. 另外,在增加信号量后, ...
- 计算机网络通信、线程、tcp、udp通信及信号量等读书笔记
一.计算机网络 1.什么是计算机网络:把分布在不同地理位置的计算机与专门的网络设备用通信线路互相连成一个规模大.功能强的系统,从而使众多计算机可以方便地互相传递信息.共享软件.硬件.数据信息等.简单来 ...
- linux io 学习笔记(01)---锁,信号量
1.采用信号量访问:当有段临界代码,需要保证排他的访问一个资源. 2.sudo dmesg -c 消除dmesg缓冲 3.互斥锁:代表的是一种锁资源,互斥锁的工作原理是:保证对共享资源操作的原子性 ...
随机推荐
- Solution -「多校联训」战神归来
\(\mathcal{Description}\) Link. 一条地铁线路上共 \(m\) 个站点,\(n\) 个人乘坐地铁,第 \(i\) 个人需要从 \(s_i\) 站坐到 \(e_i\ ...
- 5道面试题,拿捏String底层原理!
原创:微信公众号 码农参上,欢迎分享,转载请保留出处. String字符串是我们日常工作中常用的一个类,在面试中也是高频考点,这里Hydra精心总结了一波常见但也有点烧脑的String面试题,一共5道 ...
- C#字符串Unicode转义序列编解码
C#字符串Unicode转义序列编解码 在开发过程中时常会遇到"\Uxxxx"格式表示的字符,实际上"xxxx"是字符的Unicode码的十六进制表示方式.这种 ...
- CentOS单机安装k8s并部署.NET 6程序 压测 记录
前面部分依照CentOS单机安装k8s并部署.NET 6程序来进行,内存.cpu.centos版本一致,之前222元买的三年8M 2c4g腾讯云轻量服务器,这个教程算是写的很详细的了,基本可以一致执行 ...
- k8s节点简介、移除节点、新增节点
简介 Node是Pod真正运行的主机,可以是物理机也可以是虚拟机. Node本质上不是Kubernetes来创建的, Kubernetes只是管理Node上的资源. 为了管理Pod,每个Node节点上 ...
- SQL SERVER 学习过程(一)
还记得以前在学校的学习过数据库SQL SERVER 2008 R2 的教程,从学校毕业出来后的哪家单位基本没怎么使用过数据库,现在也忘得差不多了 做些相关的练习熟悉熟悉 --创建数据库-- creat ...
- linux系统挂载磁盘
linux系统挂载磁盘 ## 将硬盘挂载到/mnt/disk1下 # 检查磁盘状态,确认分区 fdisk -l # 格式化磁盘(分区) mkfs.ext4 /dev/sda #根据机器上的命名 以sd ...
- AlertDialog的五种样式
建立DialogActivity.java文件: 1 public class DialogActivity extends AppCompatActivity { 2 private Button ...
- CNN(卷积神经网络)入门
参考博文: 深度学习基础--卷积--1*1的卷积核与全连接的区别:https://blog.csdn.net/wydbyxr/article/details/84061410 如何理解卷积神经网络中的 ...
- 动态线程池(DynamicTp)之动态调整Tomcat、Jetty、Undertow线程池参数篇
大家好,这篇文章我们来介绍下动态线程池框架(DynamicTp)的adapter模块,上篇文章也大概介绍过了,该模块主要是用来适配一些第三方组件的线程池管理,让第三方组件内置的线程池也能享受到动态参数 ...