C#多线程死锁介绍与案例代码

一、死锁简介

在多道程序设计环境下,多个进程可能竞争一定数量的资源,。一个进程申请资源,如果资源不可用,那么进程进入等待状态。如果所申请的资源被其他等待进程占有,那么该等待的进程有可能无法改变状态,这种情况下称之为死锁。

二、死锁条件

死锁的四个条件:

1.非抢占:资源不能被抢占
2.互斥:至少有一个资源必须处在非共享模式,即一次只能有一个进程使用,如果另一进程申请该资源,那么申请进程必须延迟直到该资源释放为止。
3.占有并等待:一个进程必须占有至少一个资源,并等待另一个资源,而该资源为其他进程所占有。
4.循环等待:有一组进程{P0,P1,…Pn},P0等待的资源被P1占有,P1等待的资源被P2占有,Pn-1等待的资源被Pn占有,Pn等待的资源被P0占有。

形成死锁必须要满足这四个条件。那么违背这几个条件中的任何一个就不会形成死锁,这种方式成为 死锁预防,而死锁避免是动态的检测分配资源的状态是否安全。

三、解决办法

1.我们可以通过对锁加时效性,或者死锁检测来处理。

2.Monitor.TryEnter()方法。虽然这种方法可以解决死锁问题,但是最好还是不要出现死锁这种情况。

死锁案例代码

如下代码实现创建两个线程t1和t2,分别起初分配占用lock1和ock2资源。当一个线程t1占用资源lock1时,再去请求另外一个资源lock2时,此时由于另外一个线程t2在正占用资源t2,请求失败,等待释放资源。同时t2又发出请求资源lock1,但是lock1又被t1占用,没有释放,也只能进行等待。此时两个线程只能等待一直等待对方释放资源,这就称之为死锁。

namespace Deadlock
{
    class DL
    {
        int field1 = 0;
        int field2 = 0;
        private object lock1 = new int[1];
        private object lock2 = new int[1];

        public void First(int val)
        {
            lock (lock1)
            {
                Console.WriteLine("First: Acquired lock 1: "
                    + Thread.CurrentThread.GetHashCode() + " Now Sleeping.");

                //Try commenting Thread.Sleep()
                Thread.Sleep(1000);//此时t2线程占用资源

                Console.WriteLine("First: Acquired lock 1: "
                    + Thread.CurrentThread.GetHashCode() + " Now wants lock2.");

                //当请求锁lock2时,lock被t2线程占用,等待释放
                lock (lock2)
                {
                    Console.WriteLine("First: Acquired lock 2: "
                        + Thread.CurrentThread.GetHashCode());
                    field1 = val;
                    field2 = val;
                }
            }
        }

        public void Second(int val)
        {
            lock (lock2)
            {
                Console.WriteLine("Second: Acquired lock 2: "
                    + Thread.CurrentThread.GetHashCode());
                //当请求锁lock1时,lock1被t1线程占用,等待释放
                lock (lock1)
                {
                    Console.WriteLine("Second: Acquired lock 1: "
                        + Thread.CurrentThread.GetHashCode());
                    field1 = val;
                    field2 = val;
                }
            }
        }
    }

    public class MainApp
    {
        DL d = new DL();

        public static void Main()
        {
            MainApp m = new MainApp();
            Thread t1 = new Thread(new ThreadStart(m.Run1));
            t1.Start();
            Thread t2 = new Thread(new ThreadStart(m.Run2));
            t2.Start();
            Console.ReadLine();
        }

        public void Run1()
        {
            this.d.First(10);
        }

        public void Run2()
        {
            this.d.Second(10);
        }
    }
}

到此这篇关于C#多线程之死锁的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • c# 死锁和活锁的发生及避免

    避免多线程同时读写共享数据 在实际开发中,难免会遇到多线程读写共享数据的需求.比如在某个业务处理时,先获取共享数据(比如是一个计数),再利用共享数据进行某些计算和业务处理,最后把共享数据修改为一个新的值.由于是多个线程同时操作,某个线程取得共享数据后,紧接着共享数据可能又被其它线程修改了,那么这个线程取得的数据就是错误的旧数据.我们来看一个具体代码示例: static int count { get; set; } static void Main(string[] args) { for (i

  • C# 串口接收数据中serialPort.close()死锁的实例

    最近在做一个有关高铁模拟仓显示系统的客户端程序,在这个程序中要运用串口serialPort传输数据,因为每次接收数据结束后要更新UI界面,所以就用到了的Invoke,将更新UI的程序代码封装到一个方法中,然后通过Incoke调用,程序跑起来没有任何问题,但是当你执行serialPort.close()是程序就会发生死锁,整个程序卡在那里动都动不了. 上网查了很多资料,有各种这样的说法,有的说定义一个接收数据的标志,如果在执行关闭程序是进行判断,如果数据接收完了就关闭串口,没有的话继续执行,但是经

  • 浅谈C# async await 死锁问题总结

    可能发生死锁的程序类型 1.WPF/WinForm程序 2.asp.net (不包括asp.net core)程序 死锁的产生原理 对异步方法返回的Task调用Wait()或访问Result属性时,可能会产生死锁. 下面的WPF代码会出现死锁: private void Button_Click_7(object sender, RoutedEventArgs e) { Method1().Wait(); } private async Task Method1() { await Task.D

  • C#笔试题之同线程Lock语句递归不会死锁

    前几天在网上闲逛,无意中看到有这么一道题及其答案,如下: 根据线程安全的相关知识,分析以下代码,当调用test方法时i>10时是否会引起死锁?并简要说明理由. public void test(int i) { lock(this) { if (i > 10) { i--; test(i); } } } 答:不会发生死锁,(但有一点int是按值传递的,所以每次改变的都只是一个副本,因此不会出现死锁.但如果把int换做一个object,那么死锁会发生) 当我看到这道题时,我心里只有两个答案,1.

  • C#中lock死锁实例教程

    在c#中有个关键字lock,它的作用是锁定某一代码块,让同一时间只有一个线程访问该代码块,本文就来谈谈lock关键字的原理和其中应注意的几个问题: lock的使用原型是: lock(X) { //需要锁定的代码.... } 首先要明白为什么上面这段话能够锁定代码,其中的奥妙就是X这个对象,事实上X是任意一种引用类型,它在这儿起的作用就是任何线程执行到lock(X)时候,X需要独享才能运行下面的代码,若假定现在有3个线程A,B,C都执行到了lock(X)而ABC因为此时都占有X,这时ABC就要停下

  • C#多线程死锁介绍与案例代码

    一.死锁简介 在多道程序设计环境下,多个进程可能竞争一定数量的资源,.一个进程申请资源,如果资源不可用,那么进程进入等待状态.如果所申请的资源被其他等待进程占有,那么该等待的进程有可能无法改变状态,这种情况下称之为死锁. 二.死锁条件 死锁的四个条件: 1.非抢占:资源不能被抢占2.互斥:至少有一个资源必须处在非共享模式,即一次只能有一个进程使用,如果另一进程申请该资源,那么申请进程必须延迟直到该资源释放为止.3.占有并等待:一个进程必须占有至少一个资源,并等待另一个资源,而该资源为其他进程所占

  • Java编程之多线程死锁与线程间通信简单实现代码

    死锁定义 死锁是指两个或者多个线程被永久阻塞的一种局面,产生的前提是要有两个或两个以上的线程,并且来操作两个或者多个以上的共同资源:我的理解是用两个线程来举例,现有线程A和B同时操作两个共同资源a和b,A操作a的时候上锁LockA,继续执行的时候,A还需要LockB进行下面的操作,这个时候b资源在被B线程操作,刚好被上了锁LockB,假如此时线程B刚好释放了LockB则没有问题,但没有释放LockB锁的时候,线程A和B形成了对LockB锁资源的争夺,从而造成阻塞,形成死锁:具体其死锁代码如下:

  • python 多线程死锁问题的解决方案

    死锁的原理非常简单,用一句话就可以描述完.就是当多线程访问多个锁的时候,不同的锁被不同的线程持有,它们都在等待其他线程释放出锁来,于是便陷入了永久等待.比如A线程持有1号锁,等待2号锁,B线程持有2号锁等待1号锁,那么它们永远也等不到执行的那天,这种情况就叫做死锁. 关于死锁有一个著名的问题叫做哲学家就餐问题,有5个哲学家围坐在一起,他们每个人需要拿到两个叉子才可以吃饭.如果他们同时拿起自己左手边的叉子,那么就会永远等待右手边的叉子释放出来.这样就陷入了永久等待,于是这些哲学家都会饿死. 这是一

  • 如何解决Java多线程死锁问题

    死锁问题 死锁定义 多线程编程中,因为抢占资源造成了线程无限等待的情况,此情况称为死锁. 死锁举例 注意:线程和锁的关系是:一个线程可以拥有多把锁,一个锁只能被一个线程拥有. 当两个线程分别拥有一把各自的锁之后,又尝试去获取对方的锁,这样就会导致死锁情况的发生,具体先看下面代码: /** * 线程死锁问题 */ public class DeadLock { public static void main(String[] args) { //创建两个锁对象 Object lock1 = new

  • Java多线程死锁问题详解(wait和notify)

    目录 一. synchronnized 的特性 1. 互斥性 2. 可重入性 二. 死锁问题 1. 什么是死锁 2. 死锁的四个必要条件 3. 常见的死锁场景及解决 3.1 不可重入造成的死锁 3.2 循环等待的场景 三. Object类中提供线程等待的方法 1. 常用方法 2. wait和notify的搭配使用 3. wait 和 sleep 的区别 4. 练习: 顺序打印ABC 总结 一. synchronnized 的特性 1. 互斥性 synchronized 会起到互斥效果, 这里的互

  • java 多线程死锁详解及简单实例

    java 多线程死锁 相信有过多线程编程经验的朋友,都吃过死锁的苦.除非你不使用多线程,否则死锁的可能性会一直存在.为什么会出现死锁呢?我想原因主要有下面几个方面: (1)个人使用锁的经验差异     (2)模块使用锁的差异     (3)版本之间的差异     (4)分支之间的差异     (5)修改代码和重构代码带来的差异 不管什么原因,死锁的危机都是存在的.那么,通常出现的死锁都有哪些呢?我们可以一个一个看过来,     (1)忘记释放锁 void data_process() { Ent

  • C# 文件上传下载(Excel导入,多线程下载)功能的实现代码

    废话不多说了,直接给大家贴代码,具体代码如下所示: //打开Excel文件,转换为DataTable DataTable dtExcel; private void OpenFile() { OpenFileDialog dialog = new OpenFileDialog(); dialog.Filter = "Microsoft Excel files(*.xls)|*.xls;*.xlsx"; //筛选打开文件类型 :图片 *.jpg|*.jpg|*.bmp|*.bmp ;&q

  • java多线程消息队列的实现代码

    本文介绍了java多线程消息队列的实现代码,分享给大家,希望对大家有帮助,顺便也自己留个笔记 1.定义一个队列缓存池: //static修饰的成员变量和成员方法独立于该类的任何对象.也就是说,它不依赖类特定的实例,被类的所有实例共享. private static List<Queue> queueCache = new LinkedList<Queue>(); 2.定义队列缓冲池最大消息数,如果达到该值,那么队列检入将等待检出低于该值时继续进行. private Integer

  • java多线程Thread的实现方法代码详解

    之前有简单介绍过java多线程的使用,已经Thread类和Runnable类,为了更好地理解多线程,本文就Thread进行详细的分析. start() 我们先来看看API中对于该方法的介绍: 使该线程开始执行:Java 虚拟机调用该线程的 run 方法. 结果是两个线程并发地运行:当前线程(从调用返回给 start 方法)和另一个线程(执行其 run 方法). 多次启动一个线程是非法的.特别是当线程已经结束执行后,不能再重新启动. 用start方法来启动线程,真正实现了多线程运行,这时无需等待r

  • java避免死锁的常见方法代码解析

    死锁 索是一个非常有用的工具,运用场景非常多,因为它使用起来非常简单,而且易于理解.但同时它也会带来一些困扰,那就是可能会引起死锁,一旦产生死锁,就会造成系统功能不可用.让我们先来看一段代码,这段代码会引起死锁,使线程 thread_1 和线程 thread_2 互相等待对方释放锁. package thread; public class DeadLockDemo { private static String A = "A"; private static String B = &

随机推荐