依据情况的不同,过度同步可能会导致性能降低、死锁,甚至不确定的行为。
为了避免活性失败和安全性失败,在一个被同步的方法或者代码块中,永远不要放弃对客户端的控制。换句话说,在一个被同步的区域内部,不要调用设计成要被覆盖的方法,或者是由客户端以函数对象的形式提供的方法。从包含该同步区域的角度来看,这样的方法是外来的(alien)。这个类不知道该方法会做什么事情,也无法控制它。根据外来方法的作用,从同步区域中调用它会导致异常、死锁或者数据损坏。通常,你应该在同步区域内做尽可能少的工作。
如果一个可变类要并发使用,应该使这个类变成线程安全的,通过内部同步,你还可以获得明显比外部锁定整个对象更高的并发性。否则,就不要在内部同步。让客户在必要的时候从外部同步。(StringBuffer实例几乎总是被用于单个线程中,而它们执行的却是内部同步。因此,这种StringBuffer都应该用StringBuilder代替。)
简而言之,为了避免死锁和数据破坏,千万不要从同步区域内部调用外来方法。更为一般地讲,要尽量限制同步区域内部的工作量。当你在设计一个可变类的时候,要考虑一下它们是否应该自己完成同步操作。在现在这个多核的时代,这比永远不要过度同步来得更重要。只有当你有足够的理由一定要在内部同步类的时候,才应该这么做,同时还应该将这个决定清楚地写到文档中。
网友评论