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.互斥锁:代表的是一种锁资源,互斥锁的工作原理是:保证对共享资源操作的原子性 ...
随机推荐
- JwtAccessTokenConverter问题整理
Cannot convert access token to JSON 授权服务颁发token(未进行公私钥加密)后,携带此token请求资源服务,提示此错误. 使用token可以在线解析,跟踪代码后 ...
- 【Kotlin】初识Kotlin之面向对象
[Kotlin]初识Kotlin之面向对象 1.类 在Kotlin中,类用关键字class来定义 如果一个类具有类体,那么需要使用{ }来写类体内容,如果不需要类体,那么只需要定义类名就可以了 // ...
- PDF太大怎么办?缩小PDF的4种常用方法
PDF太大怎么变小?我们在平时学习或生活中经常需要上传或提交一些资料,现在网站都是默认需要提交PDF格式的电子文档,有时提交资料会提示超过系统大小,如何才能使PDF缩小呢? 一.在线压缩 首先搜索sp ...
- CVE-2021-40449 NtGdiResetDC UAF
背景 CVE-2021-40449是一个存在于Win32k内核驱动中的UAF漏洞.该漏洞在2021年八月下旬九月上旬被Kaspersky发现用于野外攻击活动中.通过Hook win32k驱动执行N ...
- 『无为则无心』Python基础 — 61、Python中的迭代器
目录 1.迭代的概念 2.迭代器的概念 3.可迭代的对象(Iterable) 4.迭代器对象(Iterator) 5.迭代器的使用体验 (1)基本用法 (2)实际应用 1.迭代的概念 (1)什么是迭代 ...
- 业务人员可以进行自助ETL操作?这款BI工具你值得拥有
ETL是什么? ETL,是英文 Extract-Transform-Load 的缩写,用来描述将数据从来源端经过抽取(extract).转换(transform).加载(load)至目的端的过程.E ...
- Smartbi集成性怎么样,是否方便与已有的Web应用集成?
Smartbi产品具有强大的集成能力,它采用纯JAVA开发,支持J2EE系统的嵌入式部署,它对外提 供所有功能的API访问接口,可以实现灵活的控制,能够方便无缝与已有的Web应用进行集成. 支持丰富 ...
- Linux:査看文件的详细信息
Linux中stat是査看文件详细信息的命令. 1.命令格式: stat [选项] 文件名/目录名 2.选项: -f:査看文件所在文件系统信息,而不是査看文件信息. 3. 案例 案例1:査看文件的详细 ...
- 爬虫之爬取B站视频及破解知乎登录方法(进阶)
今日内容概要 爬虫思路之破解知乎登录 爬虫思路之破解红薯网小说 爬取b站视频 Xpath选择器 MongoDB数据库 爬取b站视频 """ 爬取大的视频网站资源的时候,一 ...
- c# 导出Excel模板(在项目中有现成的Excel模板)
在项目中会有导出模板功能,把现成的Excel模板导出去填写之后再进行导入,这里说说怎么导出模板: 模板存放位置: 点击导出模板按钮: private string currentPath = Pat ...