转自:http://blog.csdn.net/hulihui/article/details/3319948(不过原文部分有错,我进行了修改)
Jeffrey Richter在《Windows核心编程(第5版)》中描述了一个死锁情况:假设线程Thread1和Thread2均需要独占方式访问互斥资源 m_res1、m_res2,应用互斥对象Monitor在使用前Enter(相当于加锁)、使用后Exit(相当于解锁)。由于涉及到两个资源,此时需 要特别注意加锁的顺序。如果两个线程的加锁顺序不同(Thread1先锁m_res2、Thread2先锁m_res1),此时容易发生死锁。依据该思 路,下面给出了C#实现的完整程序代码:
class Program { private static object m_res1 = new object(); private static object m_res2 = new object(); private static int m_count = 0; static void Main(string[] args) { Thread t1 = new Thread(Thread1); Thread t2 = new Thread(Thread2); t1.Start(); t2.Start(); while (true) { int preCount = m_count; Thread.Sleep(0); // 放弃当前线程的CPU时间片,Windows可能调度其他线程 if (preCount == m_count) // 数据没有变化,表明线程没有执行 { Console.WriteLine("dead lock! count: {0}", m_count); } } } private static void Thread1() { while (true) { Monitor.Enter(m_res2); // 先锁 m_res2 Monitor.Enter(m_res1); // 再锁 m_res1 m_count++; Monitor.Exit(m_res1); // 释放锁不存在先后关系 Monitor.Exit(m_res2); } } private static void Thread2() { while (true) { Monitor.Enter(m_res1); // 先锁 m_res1 Monitor.Enter(m_res2); m_count++; Monitor.Exit(m_res1); Monitor.Exit(m_res2); } } }
运行上述程序时,一般计数到300左右(笔者的机器)就发生死锁现象了。其原因为:如果Thread1锁住m_res2同时、Thread2获得 m_res1的锁,那么Thread1就不能获得m_res1的锁,当然Thread2也不能获得m_res2的锁。这两个线程都不能继续下去,于是 m_count的值没有变化。
如果线程Thread1的加锁顺序与线程Thread2相同,即:
Monitor.Enter(m_res1); Monitor.Enter(m_res2);
此时,将不会出现死锁情况:Thread1锁住m_res1且申请锁m_res2,Thread2锁住m_res2并申请m_res1。原因:因为Thread2锁住m_res2时要么是先锁住了m_res1,要么是释放m_res1时来不及释放m_res2。第一种现象不可能, 因为Thread1锁住了m_res1;第二种现象是释放锁,不存在马上申请锁。所以,顺序相同时不会出现死锁情况。(这段话很有问题,我也看不明白)
解决的方法还有:使用bool Monitor.TryEnter()方法,尝试加锁并设定一个时间上界。如果锁不住,则放弃加锁,做其他操作。
总结:在多线程对多个资源加锁时,一定要按相同的顺序。
相关推荐
通过结合C#的`Process`类、异常处理机制以及托盘图标功能,我们可以构建一个有效的进程监控系统,实时检测程序崩溃和死锁,同时在后台静默运行。这样的工具对于开发者来说极其有用,能够帮助他们及时发现和解决可能...
本文档是使用C#编写的银行家算法避免死锁的程序设计。里面包含数组初始化,利用递归判断输入整数,输出安全序列等函数,希望对大家有帮助。如有错误,请多多指教~
本次课程设计的内容是采用银行家算法,编写和调试一个仿真模拟银行家算法避免死锁的程序。设计5个并发进程共享3类不同的系统资源,即A类资源、B类资源、C类资源和可用资源数量A类资源、B类资源、C类资源。系统进行...
每个实例都旨在解决一个具体的问题或实现一个特定的功能,通过这些实例的学习,读者可以加深对C#语法、.NET框架以及编程最佳实践的理解,从而提升自己的编程技能。这些实例覆盖了从基础到高级的各种主题,适合不同...
本次课程设计通过编写和调试一个仿真模拟银行家算法避免死锁的程序,观察产生死锁的条件,并采用银行家算法,有效地避免死锁的发生。这是我们的操作系统课程设,用.net做的。 银行家算法避免死锁,其中有三个模块,...
下面通过一个具体的例子来展示如何创建一个简单的线程: ```csharp using System; using System.Threading; public class ThreadExample { // 线程执行方法 public static void ThreadProc() { for (int i = 0...
本项目“基于C#与多线程技术实现的文件管理系统程序”就是一个典型的应用实例,它利用了Microsoft的Visual Studio 2005和C#编程语言的强大功能,为用户提供高效、稳定的文件操作解决方案。下面,我们将深入探讨这个...
每个客户端连接通常会对应一个独立的线程,这样可以确保每个客户端的活动不会阻塞其他客户端。线程池管理可以优化资源分配,提高系统的响应速度。 2. Socket编程:Socket是网络通信的核心,它提供了进程间的网络...
(1)请设计一个程序演示死锁避免算法(银行家算法)。 (2)要求该演示程序可以指定任意的进程数量、资源种类、每种资源总数量(大于等于1)、已分配数量、最大需求数量,同时也可以随机生成上述数值进行模拟(随机...
在IT领域,尤其是在Java开发中,死锁是一个常见的问题,它会导致程序的执行停滞不前。本文将深入探讨如何利用“dump线程”这一技术来分析和解决死锁问题。我们将从以下几个方面来理解这个主题: 1. **什么是死锁**...
5. **定期检测和中断死锁**:SQL Server提供了一个名为`DEADLOCK_PRIORITY`的选项,允许为事务指定优先级,当发生死锁时,优先级低的事务会被强制回滚。此外,SQL Server自带的死锁检测机制也会自动发现并解决死锁,...
4. **EFLockErrorConsole项目分析**:这个子文件很可能是包含一个控制台应用程序,用于模拟和展示EF中的事务死锁。可能的实现包括创建两个并发运行的线程,每个线程使用EF进行不同的数据库操作,通过这种方式引发...
在C#编程中,多线程是一个至关重要的概念,尤其在现代高性能计算和并发处理的场景下。本讲座将深入探讨C#中的多线程技术,包括同步、死锁等关键知识点。 首先,多线程是指在一个应用程序中同时运行多个执行线程。这...
主线程负责维护一个消息泵,这个泵不断从消息队列中取出消息并处理,保持应用程序的响应状态。消息队列中的消息主要来源于用户交互或系统事件,如按键、鼠标点击等。主线程通过`GetMessage()`方法阻塞等待消息,确保...
下面是一个简单的C#实现程序互斥运行的示例: ```csharp using System; using System.Threading; class Program { private static Mutex mutex = new Mutex(true, "Global\\MyUniqueMutexName"); static void ...
总的来说,“C#_欧拉角转换方向余弦矩阵_WPF”项目是一个很好的实践,它结合了数学、编程和用户界面设计,帮助开发者更好地理解和应用三维旋转变换。通过这个工具,用户可以快速、准确地进行欧拉角到方向余弦矩阵的...
在C#编程语言中,多线程是一种强大的技术,它允许程序同时执行多个任务,从而提高了应用程序的效率和响应性。本源码示例是基于C#和Visual Studio 2005(VS2005)开发的,旨在帮助开发者理解和实践多线程处理的复杂...
【标题】"用C#编写的Winform通信程序"是一个基于C#开发的Windows桌面应用程序,主要用于实现点对点通信。这个程序的核心功能是利用UDP(User Datagram Protocol)协议进行数据传输,同时结合多线程技术来提升通信的...
在多线程编程中,死锁是一个常见的问题,特别是在C#这样的高级编程语言中。死锁发生时,两个或更多的线程互相等待对方释放资源,导致它们都无法继续执行。了解死锁并掌握解决策略是每个专业开发者的必备技能。 死锁...