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. 2020年的第一天-我的IDEA出现This license ... has been cancelled

    IDEA激活在1月3日的早上,激活码被取消了.提示:This license ... has been cancelled. 经过查询.解决方法教程无非是. ¥%--&*(激活码... 210 ...

  2. elk监听Java日志发送微信报警

    一年前写过logstash根据日志关键词报警 ,今年重温一下.并且记录一下遇到的问题解决办法. Java错误日志一般出现一大坨,如下图: 所以我们的filebeat日志收集器就要改成多行匹配模式,以日 ...

  3. [题解]hihoCoder挑战赛18——题目1 神奇字符串

    题目地址:http://hihocoder.com/problemset/problem/1264 时间限制:20000ms 单点时限:1000ms 内存限制:256MB 描述 我们说两个字符串是非常 ...

  4. 【C# 线程】interLocked锁

    overview 同步基元分为用户模式和内核模式 用户模式:Iterlocked.Exchange(互锁).SpinLocked(自旋锁).易变构造(volatile关键字.volatile类.Thr ...

  5. .net 技术大全

    我常说C#的入门技术是委托.事件.消息.只有当你可以纯熟运用这三个技能的时候,才刚刚入门,此时C#的大门才算正式为你打开.很多人在学了一些语法编写一些项目后就觉得C#精通了,其实你们还没入门呢(对日开 ...

  6. 【C#反射】开篇

    微软官方教程:https://docs.microsoft.com/zh-cn/dotnet/framework/reflection-and-codedom/viewing-type-informa ...

  7. Nullable<T> 结构 |T? 可为空的值类型

    参考链接:https://www.cnblogs.com/tdfblog/p/Nullable-Types-in-Csharp-Net.html https://www.cnblogs.com/min ...

  8. Hive常用函数大全-数值计算

    1 1.取整函数:round(X)(遵循四舍五入) 2 select round(3.1415926) from table --3 3 select round(3.5) from table -- ...

  9. linux下确认裸盘是否使用-渐入佳境

    --作者:飞翔的小胖猪 --创建时间:2021年3月9日 6.1 概述 在私有云和虚拟化环境中业务方经常会根据自己的业务情况申请磁盘用作数据存储用.如果申请了磁盘但没有使用的情况,将极大的造成资源的浪 ...

  10. Codeforces Round #750 (Div. 2) E. Pchelyonok and Segments

    传送门 题目大意: 给一个序列,可以在这个序列中从左至右选若干个段,第i段的长度为i,对于任意的段i,段内元素和S[i]<S[i+1],求在该序列中最多可以选出几段. 思路:设dp[i][j]为 ...