我们有一个使用(第三方)ActiveX 控件的 Windows 窗体应用程序,并且在“.NET CLR 内存”下的 .NET 性能对象中注意到正在使用的“同步块(synchronized block)”的数量不断增加(随着随着内存使用量的增加),即使我们的应用程序闲置在那里。
接收器 block 计数状态的内置解释:
This counter displays the current number of sync blocks in use. Sync blocks are per-object data structures allocated for storing synchronization information. Sync blocks hold weak references to managed objects and need to be scanned by the Garbage Collector. Sync blocks are not limited to storing synchronization information and can also store COM interop metadata. This counter was designed to indicate performance problems with heavy use of synchronization primitives.
当我们切换到不同的应用程序时,同步块(synchronized block)计数似乎会重置。究竟是什么导致了这些创建,是否有减少这些数量的提示?
(顺便说一句,它确实在性能计数器列表中拼写为“sink block”。我不确定这是打字错误还是管道笑话)
最佳答案
每次您在 .NET 平台中使用诸如 lock
或 Monitor.Enter
之类的锁定原语时,都会针对要锁定的对象实例初始化一个同步块(synchronized block)结构。如定义中所述,这些 block 可以保存更多信息,例如对象的哈希码和 COM 互操作信息。
由于这些 block 在可以存储的内容上是有限的,同时访问这些 block 会导致争用,这反过来会导致对象 header 的内容成为 CLR 管理的系统范围同步块(synchronized block)表的索引。 CLR 能够在对象需要时回收这些同步块(synchronized block)。
在等待系统内核对象之前,锁定对象总是会导致 CPU 旋转。每当分配的 CPU 自旋不满足以允许监视器获取临界区锁时,系统自动重置事件句柄将被创建,并且对它的引用将被放入关联的同步块(synchronized block)中。等待此事件句柄的其他线程随后将阻塞事件句柄,直到拥有线程触发事件句柄的释放。
因此,如果此计数器不断增加,则表明有太多线程争用一个或多个对象的锁,并且这些锁可能永远不会被释放。
关于c# - 什么是 "Sync Block"以及减少计数的技巧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1803298/