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信号量与死锁的边缘的更多相关文章

  1. [并发编程 - 多线程:信号量、死锁与递归锁、时间Event、定时器Timer、线程队列、GIL锁]

    [并发编程 - 多线程:信号量.死锁与递归锁.时间Event.定时器Timer.线程队列.GIL锁] 信号量 信号量Semaphore:管理一个内置的计数器 每当调用acquire()时内置计数器-1 ...

  2. C++多线程框架-----Mutex互斥和Sem信号量

           互斥和信号量是多线程编程的两个基础,其原理就不详细说了,大家去看看操作系统的书或者网上查查吧. 对于互斥的实现,无论什么操作系统都离不开三个步骤 1.初始化互斥锁 2.锁操作 3.解锁操 ...

  3. JAVA通过信号量避免死锁

    死锁是这样一种情形:多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放.由于线程被无限期地阻塞,因此程序不可能正常终止. 导致死锁的根源在于不适当地运用"synchronized ...

  4. python基础--GIL全局解释器锁、Event事件、信号量、死锁、递归锁

    ps:python解释器有很多种,最常见的就是C python解释器 GIL全局解释器锁: GIL本质上是一把互斥锁:将并发变成串行,牺牲效率保证了数据的安全 用来阻止同一个进程下的多个线程的同时执行 ...

  5. 利用多个sem信号量在线程通讯

    直接上代码,主要用到sem_trywait & sem_post #include<stdio.h> #include<pthread.h> #include<s ...

  6. 信号量sem 的用法

    #include <semaphore.h> sem_t sem; sem_init(&sem, 0, 0); sem_post(&sem); sem_wait(& ...

  7. linux 进程间信号量管理程序之sem_timedwait使用

    在开发过程中,有三个独立执行的程序模块,三个模块都对sqlite数据库进行读写操作.sqlite在linux共享性较差,所以须要增加相互排斥信号量解决三个模块訪问数据库该问题. 另外,在增加信号量后, ...

  8. 计算机网络通信、线程、tcp、udp通信及信号量等读书笔记

    一.计算机网络 1.什么是计算机网络:把分布在不同地理位置的计算机与专门的网络设备用通信线路互相连成一个规模大.功能强的系统,从而使众多计算机可以方便地互相传递信息.共享软件.硬件.数据信息等.简单来 ...

  9. linux io 学习笔记(01)---锁,信号量

    1.采用信号量访问:当有段临界代码,需要保证排他的访问一个资源. 2.sudo  dmesg -c 消除dmesg缓冲 3.互斥锁:代表的是一种锁资源,互斥锁的工作原理是:保证对共享资源操作的原子性 ...

随机推荐

  1. MySQL基本数据类型与约束条件

    昨日内容回顾 数据存储的演变 # 方向: 朝着更加统一和方便管理 数据库的发展史 # 由本地保存逐步演变为线上保存 数据库的本质 # 本质上就是一款CS架构的软件 """ ...

  2. CobaltStrike逆向学习系列(2):Stageless Beacon 生成流程分析

    这是[信安成长计划]的第 2 篇文章 关注微信公众号 [信安成长计划] 0x00 目录 0x01 Patch Beacon 0x02 Patch Loader 0x03 文件对比 0x04 流程图 C ...

  3. 网络测试技术——802.1X_MD5认证(下篇)

    上篇我们讲到802.1X_MD5的简介.认证过程.测试组网以及测试环境准备,本期我们将为大家带来测试的详细步骤: 六.测试仪配置 1.占用端口 端口功能 (1)端口1用来模拟DOT1X和发送流量 (2 ...

  4. windows server 2012 r2 修改administrator密码

    转至:https://jingyan.baidu.com/article/b907e627b615b646e7891cbf.html 1.进入开始面板,点击"管理工具". 2.双击 ...

  5. 常用的一些性能查询sql语句

    转至:https://blog.csdn.net/bosschen/article/details/84829912 --查看表锁 select * from sys.v_$sqlarea where ...

  6. Linux命令(ping-telnet-netstat-curl-ps)

    转至:https://www.jianshu.com/p/577bbd15a6f8 1.ping命令 ping命令用来测试主机之间网络的连通性.执行ping指令会使用ICMP传输协议,发出要求回应的信 ...

  7. Solon 1.6.30 发布,更现代感的应用开发框架

    相对于 Spring Boot 和 Spring Cloud 的项目 启动快 5 - 10 倍 qps 高 2- 3 倍 运行时内存节省 1/3 ~ 1/2 打包可以缩小到 1/2 ~ 1/10(比如 ...

  8. thinkPHP ajax 状态修改(上架修改为下架)

    <td> {if $v.status==1} <span class="top{$v.id}" name="0" onclick=" ...

  9. MySQL 8.0安装以及初始化错误解决方法

    MySQL 8.0 安装配置及错误排查 官网下载 CentOS7环境下的具体安装步骤 初始化MySQL发生错误的解决方法 忘记数据库root密码 官网下载 mysql官网下载链接:https://de ...

  10. 软件工程homework-001

          一. 回顾你过去将近3年的学习经历 1.当初你报考的时候,是真正喜欢计算机这个专业吗? 答:不喜欢,高中时候就已经对计算机比较抵触了,家里小时候比较富裕,九几年就在日本买了第一批家用台式机 ...