C#的两种常见的死锁情况
工作中遇到的两种线程锁死的情况,特此记录:
1.Thread1和Thread2抢占同一对象中的2个锁obj1和obj2,对象如下:

1 public class Test 2 { 3 object _obj1; 4 object _obj2; 5 public Test() 6 { 7 _obj1 = new object(); 8 _obj2 = new object(); 9 } 10 public void Test1(string name)//线程1调用 11 { 12 lock (_obj1) 13 { 14 Console.WriteLine(name + " Lock Obj1"); 15 lock (_obj2) 16 { 17 Console.WriteLine(name + " Lock Obj2"); 18 } 19 Console.WriteLine(name + " Release Obj2"); 20 } 21 Console.WriteLine(name + " Release Obj1"); 22 } 23 public void Test2(string name)//线程2调用 24 { 25 lock (_obj2) 26 { 27 Console.WriteLine(name + " Lock Obj2"); 28 lock (_obj1) 29 { 30 Console.WriteLine(name + " Lock Obj1"); 31 } 32 Console.WriteLine(name + " Release Obj1"); 33 } 34 Console.WriteLine(name + " Release Obj2"); 35 } 36 }
调用方式如下:

1 static void Main(string[] args) 2 { 3 Test p = new Test(); 4 Thread th = new Thread(() => 5 { 6 while (true) 7 { 8 p.Test1(Thread.CurrentThread.ManagedThreadId.ToString()); 9 } 10 }); 11 th.Start(); 12 th = new Thread(() => 13 { 14 while (true) 15 { 16 p.Test2(Thread.CurrentThread.ManagedThreadId.ToString()); 17 } 18 }); 19 th.Start(); 20 }
此种情况导致Thread1占用obj1等待obj2,Thread2占用obj2等待obj1,两个线程均阻塞导致死锁情况发生。执行最终如下:
解决方案:1.编程中不要使用这种嵌套写法;2.使用Monitor.TryEnter()方法。
2.Winform主线程抢占对象中的锁obj1,对象子线程占用obj1使用invoke方法调用,对象类如下:

1 public class Test 2 { 3 string str; 4 Form1 form; 5 object _obj1; 6 public Test(Form1 f) 7 { 8 this.form = f; 9 _obj1 = new object(); 10 Thread th = new Thread(Monitor); 11 th.IsBackground = true; 12 th.Start(); 13 } 14 void Monitor()//将字符串显示在UI界面 15 { 16 while (true) 17 { 18 Thread.Sleep(50); 19 lock (_obj1) 20 { 21 form.Show(str); 22 } 23 } 24 } 25 public void Test1()//UI调用,修改字符串的值 26 { 27 lock (_obj1) 28 { 29 str = DateTime.Now.ToString("HH:mm:ss:fff"); 30 } 31 } 32 }
Winform代码如下:

1 Test t; 2 public Form1() 3 { 4 InitializeComponent(); 5 t = new Test(this); 6 } 7 public void Show(string txt)//子线程占用锁时来操作控件 8 { 9 if (this.InvokeRequired) 10 this.Invoke(new Action<string>(Show), txt); 11 else 12 this.label1.Text = txt; 13 } 14 private void timer1_Tick(object sender, EventArgs e) 15 { 16 t.Test1();//定时器不停地调用 17 }
启动后可看到程序会卡死,字符串不再刷新。
解决方案:使用BeginInvoke方法替换Invoke;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)