领先的中文IT技术网站    IT技术从现在起飞

飞诺旗下: 技术社区 | 在线电子书 | 在线试题 | 资源下载 | 飞诺搜索 | 技术博客
用户名: 密   码:
   飞诺网 加入收藏
飞诺网 Asp.net 新闻频道 开发频道 系统频道 服务器 网络频道 网络安全 Java频道 C/C++ PHP开发 电子书 资源下载 社 区 博 客 在线试题
网站开发 VBScript ASP Asp.net Jsp php XML CGI-Perl 搜索引擎 ajax
编程开发 JAVA C/C++ C++ VC C语言 VB C# Delphi Foxpro 汇编 shell编程 游戏开发 软件工程师 WEB开发 PHP ASP Asp.net JSP AJAX CGI JavaScript HTML CSS 数据库 MSSQL Mysql Oracle Access Sybase DB2 sql2005 Office Word Excel Powerpoint Wps 认证考试 二级C语言 三级网络 程序员 网络工程师 思科认证

您当前的位置:飞诺网 >> .net >> Asp.net实例教程

一个简单的C#死锁程序

www.firnow.com    时间 : 2008-11-17  作者:佚名   编辑:本站 点击:   [ 评论 ]

(原创文章·转载请注明来源:http://blog.csdn.net/hulihui)

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同时、Thread1获得m_res1的锁,那么Thread1就不能获得m_res1的锁,当然Thread2也不能获得m_res2的锁。这两个线程都不能继续下去,于是m_count的值没有变化。

如果线程Thread1的加锁顺序与线程Thread2相同,即: Monitor.Enter(m_res1);
Monitor.Enter(m_res2);
此时,将不会出现死锁情况。因为不管哪个线程锁住m_res1,另一个线程就不能对m_res1加锁,当然也就不能对m_res2加锁。于是,第一个锁住m_res1的线程就可以从容得锁住m_res2,在完成线程的相关工作后释放两个锁。解决的方法还有:使用bool Monitor.TryEnter()方法,尝试加锁并设定一个时间上界。如果锁不住,则放弃加锁,做其他操作。
如果图片或页面不能正常显示请点击这里
Asp.net实例教程推荐文章

文章评论

BBS社区热贴