同步块和同步块索引

  微软在设计基本框架时充分考虑了线程同步的问题,其结果就是CLR为每一个堆内对象都提供了支持线程同步的功能,这是同步机制的雏形。但是对每个堆内对象都分配同步块有一个较大的弊端,就是这样增大了内存的消耗。在一般的系统中,需要同步机制支持的对象可能只占少数,这样对于大多数对象来说,一个同步块的内存消耗就完全被浪费了。

  鉴于这一点,CLR采用了一种折中的办法,就是实际只为每个堆内对象分配一个同步索引,该索引中只保存一个表明数组内索引的整数。CLR在加载时会新建一个同步块数组,当某个对象需要被同步时,CLR会为其分配一个同步块,并且把该同步块在同步块数组中的索引加入该对象的同步块索引中。图7.5展示了这一机制的实现。
同步块机制包含如下的几点:

  · 在CLR被加载时初始化同步块数组。

  · 每一个被分配在堆上的对象都会包含两个额外的字段,其中一个存储类型指针,而另外一个就是同步块索引,初始时被赋值为-1。

  · 当一个线程试图使用该对象进入同步时,会检查该对象的同步索引。如果索引为负数,则会在同步块数组中寻找或者新建一个同步块,并且把同步块的索引值写入该对象的同步索引中。如果该对象的同步索引不为负值,则找到该对象的同步块并且检查是否有其他线程在使用该同步块,如果有则进入等待状态,如果没有则申明使用该同步块。

  · 当一个对象退出同步时,该对象的同步索引被赋值为-1,并且对应的同步块数组内的同步块被视为不再使用。

进入同步和退出同步,指的是调用System.Threading.Monitor的Enter方法和Exit方法,现在一般使用lock关键字。

注意:负责为对象分配同步块并且赋值同步块索引的线程本身是线程安全的。

结论:同步块是指CLR维护的同步块数组中的某个元素,负责提供线程同步的操作,当某个线程拥有了某个同步块时,其他线程就在试图访问该同步块时进入等待状态。同步索引是每个堆内对象都会分配的一个字段。

posted @ 2021-03-14 10:45  Sandglass  阅读(392)  评论(0编辑  收藏  举报