zthread学习 实例十二 线程间的协助(三)——死锁

zthread线程库 zthread线程库提供了各种线程、线程池、队列、各种锁的支持,还能跨平台哦。 立即下载

因为线程可以变为阻塞,且因为对象可以拥有互斥锁,这些锁能够阻止线程在锁被释放之前访问这个对象。所以就有可能出现这种情况,某个线程在等待另一个线程而第2个线程又在等待别的线程,以此类推,直到这个链上的最后一个线程回头等待第1个线程。这样就会得到一个由互相等待的线程构成的连续的循环,而使任何线程都不能运行——死锁。死锁的过程是很难重现的,调试的难点。

下面看一个经典的死锁问题——哲学家聚餐。

 

 

[cpp]  view plain copy
  1. #include "stdafx.h"  
  2. #include "zthread/Mutex.h"  
  3. #include "zthread/CountedPtr.h"  
  4. #include "zthread/Runnable.h"  
  5. #include "zthread/Condition.h"  
  6. #include "zthread/Guard.h"  
  7. #include "Display.h"  
  8. #include <iostream>  
  9. #include <ctime>  
  10. using namespace ZThread;  
  11. using namespace std;  
  12. //(一根)筷子  
  13. class Chopstick  
  14. {  
  15. public:  
  16.     Chopstick() : notTaken(Lock), taken(false){}  
  17.       
  18.     //拿起筷子  
  19.     void Take()  
  20.     {  
  21.         Guard<Mutex> g(Lock);  
  22.           
  23.         //如果筷子此时已被拿起,再被拿起时,必须等待  
  24.         while(taken == true)  
  25.             notTaken.wait();  
  26.         taken = true;  
  27.     }  
  28.       
  29.     //放下筷子  
  30.     void Drop()  
  31.     {  
  32.         Guard<Mutex> g(Lock);  
  33.           
  34.         taken = false;  
  35.           
  36.         //唤醒要拿起它的线程  
  37.         notTaken.signal();   
  38.     }  
  39. private:  
  40.     Mutex       Lock;  
  41.     Condition   notTaken;  
  42.     bool        taken;  
  43. };  
  44. class Philosopher : public Runnable  
  45. {  
  46. public:  
  47.     Philosopher(Chopstick& l, Chopstick& r, int idn, int ponder, CountedPtr<Display>& disp):  
  48.     left(l), right(r), id(idn), ponderFactor(ponder), display(disp)  
  49.     {  
  50.       
  51.     }  
  52.       
  53.     virtual void run()  
  54.     {  
  55.         try  
  56.         {  
  57.             while (!Thread::interrupted())  
  58.             {  
  59.                 output("Think!");  
  60.                 Thread::sleep(randSleepTime());  
  61.                   
  62.                 output("grabbing right");  
  63.                 right.Take();  
  64.                   
  65.                 output("grabbing left");  
  66.                 left.Take();  
  67.                   
  68.                   
  69.                 output("Eatting!");  
  70.                 Thread::sleep(randSleepTime());  
  71.                   
  72.                 right.Drop();  
  73.                 left.Drop();  
  74.             }  
  75.         }  
  76.         catch (Interrupted_Exception& e)  
  77.         {  
  78.             cerr << " Jarry :" << e.what() <<endl;  
  79.         }  
  80.     }  
  81.     friend ostream& operator <<(ostream& os, const Philosopher& p)  
  82.     {  
  83.         return os << "Philosopher : " << p.id;  
  84.     }  
  85.       
  86. private:  
  87.     Chopstick& left;  
  88.     Chopstick& right;  
  89.       
  90.     int id;  
  91.     int ponderFactor;  
  92.       
  93.     CountedPtr<Display> display;  
  94.       
  95.     int randSleepTime()  
  96.     {  
  97.         if (ponderFactor == 0)  return 0;  
  98.           
  99.         return rand() / (RAND_MAX / ponderFactor) * 250;  
  100.     }  
  101.       
  102.     void output(string str)  
  103.     {  
  104.         ostringstream os;  
  105.         os << *this << " : " << str <<endl;  
  106.           
  107.         display->OutPut(os);  
  108.     }  
  109. };  
  110. int _tmain(int argc, _TCHAR* argv[])   
  111. {  
  112.     srand((unsigned int)time(0));  
  113.       
  114.     const int count = 5;  
  115.       
  116.     int pender =  0;  
  117.       
  118.     try  
  119.     {  
  120.         CountedPtr<Display> disp(new Display);  
  121.           
  122.         ThreadedExecutor executor;  
  123.           
  124.         Chopstick chopstick[count];  
  125.           
  126.         for (int i = 0; i < count; i ++)  
  127.         {  
  128.             //会出现死锁,是因为出现了循环等待  
  129.             //executor.execute(new Philosopher(chopstick[i], chopstick[(i + 1) % count], i, pender, disp));  
  130.               
  131.             //打破发生死锁的第4个条件(循环等待)  
  132.             if (i < count - 1)  
  133.                 executor.execute(new Philosopher(chopstick[i], chopstick[(i + 1)], i, pender, disp));  
  134.             else  
  135.                 executor.execute(new Philosopher(chopstick[0], chopstick[i], i, pender, disp));  
  136.         }  
  137.         cin.get();  
  138.         executor.interrupt();  
  139.         executor.wait();  
  140.           
  141.         cin.get();  
  142.           
  143.     }  
  144.     catch (Synchronization_Exception& e)  
  145.     {  
  146.         cerr << " Jarry main " << e.what() <<endl;  
  147.     }  
  148.     return 0;  
  149. }  
 

如果在某一个时间点上所有的哲学家同时试图进餐,拿起同一侧的一根筷子,并且等待紧挨着他们的哲学家放下筷子,这样程序将会死锁。

 

 

 

同时满足以下4种条件,死锁就会发生:

1、相互排斥。线程使用的资源至少有一个必须是不可共享的。在这种情况下,一根筷子一次只能被一个哲学家使用。

2、至少有一个线程必须持有某一种资源,并且同时等待获得正在被另外的线程所持有的资源。也就是说要发生死锁一个哲学家必须持有一根筷子并且等待另一根筷子。

3、不能以抢占的方式剥夺一个线程的资源。所有线程只能把释放的资源作为一个正常事件。他们不会从别的哲学家手中抢夺筷子。

4、出一个循环等待。一个线程等待另外的线程所持有的资源,而这个等待的线程又等待另一个线程所持有的资源,以此类推直到某个线程去等待第一个线程所持有的资源。例子中每一个哲学家总是试图先得到右边的筷子,而后得到左边的筷子,所以发生了循环等待。

 

避免死锁只要打破以上四个条件中的一个就可以了!

ZThread-2.3.2 C++多线程库 ZThread-2.3.2 C++多线程库,在linux下编多线程程序很值得参考 立即下载

相关推荐

zthread2.3.2 代码和lib

zthread2.3.2 代码 lib zthread2.3.2 代码 lib

zthread学习 实例十 线程间的协助(三)——死锁

同时满足以下4种条件,死锁就会发生: 1、相互排斥。线程使用的资源至少有一个必须是不可共享的。在这种情况下,一根筷子一次只能被一个哲学家使用。 2、至少有一个线程必须持有某一种资源,并且同时等待获得正在被另外的线程所持有的资源。也就是说要发生死锁一个哲学家必须持有一根筷子并且等待另一根筷子。 3、不能以抢占的方式剥夺一个线程的资源。所有线程只能把释放的资源作为一个正常事件。他们不会从别的哲学家手中抢夺筷子。 4、出一个循环等待。一个线程等待另外的线程所持有的资源,而这个等待的线程又等待另一个线程所持

Jarry's World 2554

国央企创新负责人如何通过平台实现科研成果的快速识别与转化?.docx

科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。

zhtread c++多线程库的使用2

按照c++ think上面的说明继续看看写个代码如下:编程环境(vc 7.1) #include #include #include #pragma comment(lib,"ZThread_Z.lib")class thread : public ZThread::Runnable{public:    thread(int _id): id(_id){}    ~thread(){}    v

ccsdu2004的专栏 2372

ArcGIS基础:CAD数据转换为GIS数据(符号化显示、数据转换、线转面、空间连接)

1、符号化显示: CAD数据加载进来有很多列表,包含了点【point】、线【polyline】、面【polygon】、标注数据【Annotation】等数据,本次实验我们需要用到的是面数据,也就是.dwgPolygong格式的数据。如下图所示: 把数据加载进来,然后在2处打开属性表,查看CAD数据的属性表,打开后可以发现【layer】图层表示就是地块的用地性质,它就是符号化显示的依据。 我们在数据上右键【属性】,打开图层属性,找到【符号系统】,选择类别中的【唯一值】,然后在【值字段】下拉选择【layer】,

yuanYW7556的博客 2万+

手把手教你逆向京东搜索接口:H5ST 556位参数生成与V8补环境技巧

本文深入解析了京东搜索接口中关键的H5ST 556位参数生成机制,并提供了详细的逆向实战指南。针对其复杂的反爬虫环境检测,文章重点介绍了通过链式补环境技巧,在Node.js中完整模拟浏览器环境(包括原型链检测和指纹验证)的方法,帮助开发者成功绕过防护并生成有效参数。

weixin_29315091的博客 481

zhtread c++多线程库的使用

很早就买了c++编程思想第二卷这本书 可惜最后一章一直没有看。于是找个时间看看多线程也比较好啊 使用编译好的zthread库自己先写个简短的例子:如下:#include #include #pragma comment(lib,"ZThread_Z.lib")class thread : public ZThread::Runnable{public:    thread(int _id): id

ccsdu2004的专栏 1827

[特殊字符] 智能补货(AI-driven Replenishment)完整实施方案

补货量=预测需求+安全库存−当前库存补货量 = 预测需求 + 安全库存 - 当前库存补货量=预测需求+安全库存−当前库存。:基于 LSTM/Transformer 预测未来 30/60/90 天的销量。

nbsaas-boot基于Request-Response的企业级快速开发框架 967

zthread多线程库的使用6 Cancelable 类与访问控制

类canceable的作用是提供一个通用的接口 通过它 可以来改变线程的状态通过isCancelable来获取线程的状态class MyCancel : public ZThread::Cancelable { bool canceled;public: MyCancel() : canceled(false) {} virtual void Go()=0;

ccsdu2004的专栏 1549

【问题解决】解决 Python `PermissionError` 权限不足:文件/进程/端口全场景修复

本文总结了Python程序中常见的权限问题及解决方案,包括文件、进程和端口权限错误。文件权限问题通常由文件占用、权限不足或路径错误引起;进程问题多因权限不足或系统限制;端口问题则与端口占用、防火墙或特权端口相关。解决方案提供了详细的代码实现:文件权限管理器类(FilePermissionManager)包含检查权限(check_permission)、修复权限(fix_permission)、安全写入(safe_write)和安全删除(safe_delete)等方法,通过异常处理和临时文件等技术确保操作安全

博客 358

【图像超分】论文精读:Interpreting Super-Resolution Networks with Local Attribution Maps(LAM)

论文题目:Interpreting Super-Resolution Networks with Local Attribution Maps —— 用局部归因图解释超分辨率网络CVPR 2021!必读文章!必须会的可视化手段!很多文章中都会对比LAM!图像超分辨率 (SR) 技术发展迅速,受益于深度网络的发明及其连续突破。然而,众所周知,深度学习和深度神经网络很难解释。SR网络继承了这种神秘的性质,很少有作品试图理解它们。在本文中,我们对 SR 网络进行了归因分析。

主要更新底层视觉(去噪、超分等)相关的科研内容,形式为【论文精读】+【论文复现】 547

zthread库类型总结 .

Runnable            //执行任务的接口     Cancelable          //可取消任务接口     Waitable            //任务可阻塞等待接口     Thread              //线程类     ThreadedExecutor    //线程执行器,为每个Runnable任务创建一个线程     PoolExe

516

【PINN高级教程】 第1讲:函数空间与逼近理论

结论:在解决偏微分方程(PDE)时,解往往属于某个 Sobolev 空间 HsHs,其正则性受限于 PDE 的系数与边界条件;而 PINN 在训练过程中实际上是在逼近 Barron 空间中的函数。由于 Barron 空间允许高频信息的压缩,PINN 可以在参数规模较小的情况下捕捉到 PDE 解所需的细节,但其正则性保证仍然比 Sobolev 更弱。因此,在设计 PINN 时,需要通过正则化或网络结构(如残差连接、归一化层)来“逼近”Sobolev 正则性。

u012133341的博客 237

zthread学习 实例十二 ZThread库基本结构的规纳

 1、四大基类 CancelableCancelable提供了通用的方法来定义语义,调用了cancel()的Cancelable对象,将被置为disable。调用过cancel()ed的对象不必立即中止工作。通常被cancel()ed的对象尽可能快的继续执行完当前分配给它的工作,然后再变得不可用;但它不能接受任何新分配给它的工作。cancel()函数:使一个Cancelab

Jarry's World 2769

python爬虫项目(一百九十八):电商平台用户行为数据分析与推荐系统、爬取电商平台用户行为数据

本文详细介绍了如何通过爬虫技术抓取电商平台的用户行为数据,并结合数据分析技术,构建一个简单的推荐系统。使用Selenium模拟用户操作抓取动态网页数据,并通过API接口直接获取用户行为数据,能够为后续的用户行为分析提供基础数据。我们结合了基于用户协同过滤、基于商品协同过滤和矩阵分解等方法,构建了不同的推荐系统。实际应用中,可以进一步优化推荐算法,利用更复杂的深度学习技术和更高效的数据处理方法,提升推荐的准确性和个性化程度。

斌擎科技 2361

光斑定位 - MATLAB实现

光斑定位是一种常见的图像处理任务,它涉及到在图像中准确定位光斑或亮点的位置。在本篇文章中,我们将使用MATLAB来实现光斑定位的算法,并提供相应的源代码。希望本文提供的MATLAB代码和步骤能够帮助您实现光斑定位任务。通过这些代码,您可以在MATLAB环境中轻松地定位光斑,并在图像上进行可视化展示。这样,我们就完成了光斑定位算法的MATLAB实现。通过以上步骤,我们可以得到一个在光斑位置上标记的图像,从而实现了光斑的准确定位。光斑定位 - MATLAB实现。

qq_39605374的博客 764

zthread学习 实例十五ZThread库基本结构的规纳

1、四大基类  Cancelable Cancelable提供了通用的方法来定义语义,调用了cancel()的Cancelable对象,将被置为disable。调用过cancel()ed的对象不必立即中止工作。通常被cancel()ed的对象尽可能快的继续执行完当前分配给它的工作,然后再变得不可用;但它不能接受任何新分配给它的工作。 cancel()函数:使一个Cancelabl

fengliping的专栏 849

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

C++之,我是如何解决多线程阻塞与中断难题的

在C++编程的实际工作中,多线程开发是提升程序性能的有力工具,但同时也带来了一系列复杂的问题。其中,线程的阻塞与中断处理让我在项目开发中遇到了不小的挑战。今天,就和大家分享一下我在这方面的经历,以及我是如何一步步解决这些问题的。

wj_rdk的博客 1632

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

C++之,我是如何解决多线程阻塞与中断问题的

在C++编程的实际工作中,多线程编程能够显著提升程序的运行效率,但同时也引入了一系列复杂的问题,其中线程的阻塞与中断处理让我在项目开发中遇到了不小的挑战。今天,就和大家分享一下我在这方面的经历,以及我是如何一步步解决这些问题的。

wj_rdk的博客 1449

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

IBM的ZThread库

下载地址去除调试信息:在Debug.h中的最前端增加#define ZTDEBUG(x),忽略警告,DONE这个库用起来应该比Linux系统下提供的并发的借口要来的舒坦,不知道有没有TBB快速,但是可以肯定的是为程序员省掉了很多代码的编辑工作。Mark一下,认真学习之。当需要使用多线程库的时候,需要从Runnable共有继承产生一个类,然后重新定义run()函数代码如下:#include #include "zthread/Runnable.h" #include "zthread/Thread.h"

hitrose27的专栏 3222

zthread的简单使用

#include "stdafx.h" #include #include "zthread/PoolExecutor.h" #include "zthread/ThreadedExecutor.h" #include "zthread/ConcurrentExecutor.h" #include "zthread/SynchronousExecutor.h" #include "z

c1s2d3n4cs的博客 315

zthread学习 实例四 让步、休眠、优先级

1、让步 Thread::yield()可以介入CPU的调度,使CPU强制放弃执行当前线程。   2、休眠 Thread:sleep()可以使线程停止执行一段时间。 Thread:sleep()可发抛出一个Interrupted_Exception,该异常必须在run()函数中捕获,因为异常是不会跨线程传播的,只能在线程内部处理。   3、优先级 T

fengliping的专栏 671

跨平台线程库 ZThread入门

 由于要用到多线程技术,之前用过windows API,但那是windows平台的。想试一下跨平台的,网上说boost有线程库,但那是个庞然大物,编译麻烦。无意中看见Zthread,这个小巧玲珑, sourceforge就有源码下载。第一次运行就成功了,好神奇啊! 小例子:   #include &lt;iostream&gt; #include &lt;zthread/Runnable....

westice的专栏 530

ZThread学习笔记(一)

zthread是一个开源的多线程开发库,是C++语言编写的开发包的下载地址为http://zthread.sourceforge.net/关于下载编译出现问题请参考我的前一个文章,下面主要介绍zthread的主要用法,粗粗浏览了一下源代码,风格特别好,本来想在它一个叫thread的线程库中找一个学习,马上就觉得那个代码是在是太难看了,还是zthread好看,C++第二卷上也是拿这个库作为并发那

fayzhou的专栏 9766

C++类库介绍

C++类库介绍  再次体现了C++保持核心语言的效率同时大力发展应用库的发展趋势!!在C++中,库的地位是非常高的。C++之父 Bjarne Stroustrup先生多次表示了设计库来扩充功能要好过设计更多的语法的言论。现实中,C++的库门类繁多,解决的问题也是极其广泛,库从轻量级到重量级的都有。不少都是让人眼界大开,亦或是望而生叹的思维杰作。由于库的数量非常庞大,而且限于笔...

weixin_33973600的博客 165
上一篇: zthread学习 实例十一 线程间的协助(二)
下一篇: zthread学习 实例十三 线程间的协助(四)——读者、写者
StudentFlp
博客等级 码龄16年 5粉丝 0原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值