程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 揭示同步塊索引(下):總結

揭示同步塊索引(下):總結

編輯:關於.NET

前面,我用兩篇文章詳細的討論了同步塊索引在lock和GetHashCode所起的作用。不過兩篇文章是分開 來討論的。那可能有人會問,如果我有一個object,它既作為lock的lockHelper對象,也要調用它的 GetHashCode方法該怎麼辦,難道這個同步塊索引還可以承擔這兩個任務麼。同步塊索引是可以承擔這兩 個任務,但是裡面卻隱藏著更大的秘密,我們先來看看與同步塊索引相關的結構:

大致就是這樣的一個結構,一個對象的ObjectHeader中的SyncBlockIndex指向一個Sync Block Entry Table中的一項,這裡用虛線表示,是說明這裡不是使用指針直接的指向,而是一個索引,這樣有個什麼 好處呢,就是CLR可以隨便把這個Table放在哪裡,也可以按需增大這個Table的容量,反正我這裡使用的 是索引而不是指針,是間接的指向。這個Table裡的每一項都是一個SyncTableEntry,這個 SyncTableEntry有兩個字段,第一個字段是一個SyncBlock的指針,指向一個SyncBlock對象。還有一個字 段是一個Object指針,有了這個指針CLR就可以跟蹤這個SyncBlock是哪個對象的,而且SyncTableEntry和 SyncBlock不是放在GC管理的內存中,所以可以根據這個Object*來跟蹤對應的對象的實例,當對象死亡後 ,可以回收對應的SyncBlock和SyncTableEntry,不過這個Object的指針是一個弱引用(弱引用的作用是 ,如果沒有任何強引用引用該對象,則該對象可以被認為是垃圾,允許被垃圾收集)。

不過要注意的是,上面這種結構並不是一個對象“與生俱來”的,也就是說對象剛初始化的時候並不 如此。當一個對象剛初始化的時候,在ObjectHeader中,SyncBlockIndex字段是為0的,這個在上一篇文 章中的Visual Studio + SOS的實驗中我們已經見到過。而如果調用對象的GetHashCode方法,則對象的 ObjectHeader中的SyncBlockIndex字段的低26位則用來存儲該對象的HashCode,而高6位作為一個標識, 表示現在SyncBlockIndex作為存儲HashCode之用,具體做法就是將這個SyncBlockIndex與 BIT_SBLK_IS_HASHCODE (#define BIT_SBLK_IS_HASHCODE 0x04000000)作或運算,判別的時候作一下與運 算。這個在上一篇文章中也介紹了。而如果調用對象的GetHashCode方法之後,繼續將該對象作為lock的 對象使用呢?這個時候SyncBlockIndex的低26位會搖身一變,變成一個索引,而且還與 BIT_SBLK_IS_HASH_OR_SYNCBLKINDEX (#define BIT_SBLK_IS_HASH_OR_SYNCBLKINDEX 0x08000000)作一下 或運算,表示這個SyncBlockIndex現在啊既有存儲HashCode之功用,又要作為lock的對象。

那既然這低26位變成了索引,那原來的HashCode跑到哪裡去了呢?這個就要一探SyncBlock的結構了:

我們看到最後一個字段,這個字段就是如果SyncBlockIndex還做其他用途是,CLR會將計算所得的 hashcode放到這裡。而如果對象只作lock對象使用,而沒有調用GetHashCode方法,則這個字段為0。根據 調用的順序,這個m_dwHashCode的設置有兩種方式:

1、已經調用了GetHashCode方法,然後作lock之用,那這裡的m_dwHashCode就是之前存儲在 SyncBlockIndex中的低26位。

2、先作lock之用,然後調用GetHashCode,那m_dwHashCode就是當時新生成的HashCode,然後放在這 裡的。

從圖中我們還有ADIndex這麼一個字段,這個字段是表示當前這個對象屬於哪個AppDomain,實際上這 個字段也可以在SyncBlockIndex裡設置,但是如果SyncBlockIndex要擔負別的責任,比如該對象作為lock 對象時,ADIndex就在SyncBlock裡這個字段設置了。關於為什麼需要這個ADIndex我現在還沒弄清楚,等 我弄明白了,再來更新這篇文章。

SyncBlock的第一個字段是AwareLock,實際上這個東西和我第一篇文章中提到的CRITICAL_SECTION結 構是一樣的,具體細節可以參見“揭示同步索引塊(上)-從lock開始”這篇文章。

而這裡的SLink字段有兩個作用:

1、當SyncBlock是活動的時候,這個字段將作為一個隊列,保存在這裡排隊的線程(作為lock對象時 )。

2、當SyncBlock被回收時,這個字段就作為空閒的SyncBlock列表。

好了,同步塊索引的相關用途和結構在上、中、下這三篇文章中基本討論完了。沒想到這麼一個小小 的,不起眼的同步塊索引卻有這麼一番作用。從這個同步塊索引的使用上,也可以看得出來微軟的CLR Team在設計的時候,對內存、性能可謂斤斤計較,充分的利用每一個bit,一個bit的不同就會表示不同的 作用。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved