C#中Finally的一個(gè)不太常見的用法
最近在看.net BCL 傳送門 的源碼. 在
System.Collections.Concurrent.ConcurrentQueue
中看到一段有意思的代碼.注意這段代碼是寫在ConcurrentQueue這個(gè)用于并發(fā)中的隊(duì)列. 注意,這是一個(gè)無鎖隊(duì)列的實(shí)現(xiàn).
- try
- { }
- finally
- {
- newhigh = Interlocked.Increment(ref m_high);
- if (newhigh <= SEGMENT_SIZE - 1)
- {
- m_array[newhigh] = value;
- m_state[newhigh].m_value = true;
- }
- if (newhigh == SEGMENT_SIZE - 1)
- {
- Grow();
- }
- }
這其實(shí)是一個(gè)小的技巧:放在Finally中的代碼可以防止執(zhí)行線程在執(zhí)行過程中被另一個(gè)線程用調(diào)用了Thread.Abort()或Thread. Interrupt()打斷.從而保證這段代碼執(zhí)行的完整性。
舉個(gè)例子: 如果不將上面代碼放到Finally中運(yùn)行.假如正好有一個(gè)線程A執(zhí)行到 m_array[newhigh] = value;
而另外一個(gè)線程B調(diào)用了線程A的Thread.Abort()
那么m_array[newhigh] = value;
以后的代碼可能沒有機(jī)會(huì)得到執(zhí)行.那么將引起ConcurrentQueue的不完整。
而放到Finally中的代碼,即使線程B在線程A執(zhí)行時(shí)調(diào)用了Thread.Abort()或Thread. Interrupt()方法時(shí)也能保證Finally塊中的代碼被完整的執(zhí)行。
事實(shí)上,這個(gè)特性是在.net framework2.0中引入的.在.net 1.1時(shí)Finally沒有這個(gè)作用.另外 Tread.Abort有可能打斷線程內(nèi)的靜態(tài)構(gòu)構(gòu)函數(shù)執(zhí)行。
另外我認(rèn)為同樣的功能也可以用這個(gè)Thread.BeginCriticalRegion
和Thread.EndCriticalRegion();
來實(shí)現(xiàn)。