.NET线程同步问题的调试方法

问题介绍

.NET中线程同步经常用到以下方式,

线程同步经常遇到的问题有以下几种,

  • 等待 - 等待锁释放
  • 死锁 - 请求锁资源顺序不一致而造成互锁
  • 脏读 - 线程访问资源缺少同步机制保护

死锁也是等待,只是死锁的等待程序无法自解。



脏读一般用在数据库系统中的概念,即多个线程访问同一个资源过程中读与写同时进行。例如在循环遍历某个数组的时候抛出了异常报告正在遍历的数组被更改,Collection was modified; enumeration operation may not execute.

这类问题造成的原因主要是由于在写的过程中缺少排他锁,相应的解决方案可以考虑减少资源的可见度,把资源的访问控制在有限的几个特定的方法中,然后在这些特定的方法上面相应的读写处加锁来避免脏读发生。


调试方法


lock statement

调试等待问题首先还是要先确定线程对象,弄清楚谁在等谁?下面是一个使用lock statement (Monitor class)的简单线程等待的例子,3号线程在Sleep,4号线程在等待。根据调用栈我们可以知道四号线程是在调用Monitor.Enter()方法。

   3  Id: 27fc.7f0 Suspend: 1 Teb: 000007f5`ffae6000 Unfrozen
Child-SP          RetAddr           Call Site
00000000`1b9fea28 000007f8`0e6b11f2 ntdll!NtDelayExecution+0xa
00000000`1b9fea30 000007ff`f803369d KERNELBASE!SleepEx+0xaa
00000000`1b9fead0 000007ff`f7c2e7fd mscorwks!EESleepEx+0x2d
00000000`1b9feb50 000007ff`f81f0769 mscorwks!Thread::UserSleep+0x71
00000000`1b9febb0 000007ff`98500486 mscorwks!ThreadNative::Sleep+0xf9
00000000`1b9fed60 000007ff`f30d2bdb Synchronization!Synchronization.Program.ThreadProc()+0x106
00000000`1b9fee00 000007ff`f316a9bd mscorlib_ni!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)+0x9b
00000000`1b9fee50 000007ff`f7dbd552 mscorlib_ni!System.Threading.ThreadHelper.ThreadStart()+0x4d
00000000`1b9feea0 000007ff`f7cfa283 mscorwks!CallDescrWorker+0x82
00000000`1b9feef0 000007ff`f819c7af mscorwks!CallDescrWorkerWithHandler+0xd3
00000000`1b9fef90 000007ff`f7be4415 mscorwks!MethodDesc::CallDescr+0x2af
00000000`1b9ff1d0 000007ff`f7d3cda4 mscorwks!ThreadNative::KickOffThread_Worker+0x191
00000000`1b9ff4f0 000007ff`f7d23721 mscorwks!ManagedThreadBase_DispatchInner+0x2c
00000000`1b9ff540 000007ff`f7c1fc59 mscorwks!ManagedThreadBase_DispatchMiddle+0x9d
00000000`1b9ff610 000007ff`f7d7c949 mscorwks!ManagedThreadBase_DispatchOuter+0x31
00000000`1b9ff650 000007ff`f7d472d3 mscorwks!ManagedThreadBase_FullTransitionWithAD+0x35
00000000`1b9ff6b0 000007ff`f7d3f3a4 mscorwks!ThreadNative::KickOffThread+0xd3
00000000`1b9ff790 000007f8`0f16167e mscorwks!Thread::intermediateThreadProc+0x78
00000000`1b9ff8e0 000007f8`116d3501 KERNEL32!BaseThreadInitThunk+0x1a
00000000`1b9ff910 00000000`00000000 ntdll!RtlUserThreadStart+0x21

   4  Id: 27fc.2634 Suspend: 1 Teb: 000007f5`ffae4000 Unfrozen
Child-SP          RetAddr           Call Site
00000000`1bafe5c8 000007f8`0e6b12c6 ntdll!ZwWaitForMultipleObjects+0xa
00000000`1bafe5d0 000007ff`f7c1e7f9 KERNELBASE!WaitForMultipleObjectsEx+0xe5
00000000`1bafe8b0 000007ff`f7c231e1 mscorwks!WaitForMultipleObjectsEx_SO_TOLERANT+0xc1
00000000`1bafe950 000007ff`f7d203d5 mscorwks!Thread::DoAppropriateAptStateWait+0x41
00000000`1bafe9b0 000007ff`f7c3e94c mscorwks!Thread::DoAppropriateWaitWorker+0x191
00000000`1bafeab0 000007ff`f7c7d16a mscorwks!Thread::DoAppropriateWait+0x5c
00000000`1bafeb20 000007ff`f7c00fd1 mscorwks!CLREvent::WaitEx+0xbe
00000000`1bafebd0 000007ff`f7d4e002 mscorwks!AwareLock::EnterEpilog+0xc9
00000000`1bafeca0 000007ff`f815a815 mscorwks!AwareLock::Enter+0x72
00000000`1bafecd0 000007ff`98500427 mscorwks!JIT_MonEnterWorker_Portable+0xf5
00000000`1bafeea0 000007ff`f30d2bdb Synchronization!Synchronization.Program.ThreadProc()+0xa7
00000000`1bafef40 000007ff`f316a9bd mscorlib_ni!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)+0x9b
00000000`1bafef90 000007ff`f7dbd

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
当使用.NET多线程时,卡住定位通常是由于线程死锁、竞争条件或资源争用引起的。下面我会逐一解释并讨论这些问题。 1. 线程死锁:线程死锁是指两个或多个线程相互等待对方释放持有的资源而无法继续执行的情况。这通常发生在多个线程试图同时访问相同的资源,并且彼此互相持有对方需要的资源。要解决这个问题,可以使用互斥锁(Mutex)或Monitor类来同步线程,并确保资源按顺序被访问。 2. 竞争条件:竞争条件是指多个线程尝试同时更改共享资源而导致的错误行为。这可以通过使用锁定机制(例如Monitor类或lock语句)来解决,以确保每次只有一个线程可以访问共享资源。 3. 资源争用:资源争用是指多个线程尝试同时访问有限的资源而导致的性能下降。这可以通过使用线程池(ThreadPool)来处理,并将工作任务分配给可用的线程,以避免频繁地创建和销毁线程。 另外,要定位.NET多线程卡住的问题,可以使用调试工具来跟踪线程的执行路径、查看线程间的相互作用以及检查资源的使用情况。Visual Studio提供了可视化调试工具,如线程窗口和内存窗口,可以帮助我们定位和解决这些问题。 综上所述,解决.NET多线程卡住定位问题需要在编码阶段避免线程死锁、竞争条件和资源争用,并使用调试工具来定位问题并进行恰当的修复。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值