作者:不及格的程序员-八神
必备知识
同步异常:指产生异常时,是我们预想到的,可以定义捕获的.
异步异常:指代码中不可预料的异常,比如 ThreadAbortException、StackOverflowException 和 OutOfMemoryException 异常.
在CLR中的异步异常,有独特的异常码,例如 Access Violation异常码是 0xC0000005, divide by zero (integer)异常码是0xC0000094, divide by zero (floating)异常码是0xC000008E. 它们被CLR特别处理.
CLR中的同步异常就是指Throw抛出的异常对象,而它给RaiseException 的异常码为0xE0434F4D,这代表为托管异常.CLR会以SEH机制向系统注册异常处理函数来处理这些异常.
正文
原子操作与异步异常:.NET下的异步异常 ThreadAbortException,通过另一个委托线程(而不是在线程本身,那样只会产生同步异常)停止(调用Abort方法)当前线程时就会发生,它可以中断当前线程中正被执行的任何代码.
这样就会产生问题,如果我们正在同步锁定一个对象,而又碰巧发生线程中止异常,那么被锁定对象将得不到释放。
下面用简单的代码说明这种情况的发生,虽然几呼不可能.
1 using System;
2 namespace TempWebApplication1
3 {
4 public partial class Test : System.Web.UI.Page
5 {
6 private object sync = new object ();
7
8 protected void Page_Load( object sender, EventArgs e)
9 {
10 // lock生成的代码与下面是相同的
11 System.Threading.Monitor.Enter(sync);
12 doSomething(); // 理论上这里不应该有代码,但是在调试模试下,JIT会生成NOP汇编指令,这样这里会可能会被ThreadAbortException中断(几率非常小,但是你要知道这个原理),而finally则不会执行.
13 try
14 {
15 Response.Write( " abc " );
16 }
17 finally
18 {
19 System.Threading.Monitor.Exit(sync);
20 }
2 namespace TempWebApplication1
3 {
4 public partial class Test : System.Web.UI.Page
5 {
6 private object sync = new object ();
7
8 protected void Page_Load( object sender, EventArgs e)
9 {
10 // lock生成的代码与下面是相同的
11 System.Threading.Monitor.Enter(sync);
12 doSomething(); // 理论上这里不应该有代码,但是在调试模试下,JIT会生成NOP汇编指令,这样这里会可能会被ThreadAbortException中断(几率非常小,但是你要知道这个原理),而finally则不会执行.
13 try
14 {
15 Response.Write( " abc " );
16 }
17 finally
18 {
19 System.Threading.Monitor.Exit(sync);
20 }
21 }
22 }
23 }
22 }
23 }
下面是调试版本的汇编节选,可以看到nop指令的.
System.Threading. Monitor . Enter (sync) ;
mov eax,dword ptr [ebp-3Ch]
mov ecx,dword ptr [eax+00000174h]
call 726C216D
nop
try
{
nop
Response.Write( " abc " ) ;
...
mov eax,dword ptr [ebp-3Ch]
mov ecx,dword ptr [eax+00000174h]
call 726C216D
nop
try
{
nop
Response.Write( " abc " ) ;
...