让每个对象都可锁定看起来像是一个设计错误:
- 您为创建的每个对象都增加了额外成本,即使您实际上只会在一小部分对象中使用它。
- 锁的使用变得隐式,
lockMap.get(key).lock()
比任意对象上的同步更具可读性,例如,synchronize (key) {...}/
。 - 同步方法可能导致用户使用同步方法锁定对象的细微错误
- 您可以确定将对象传递给第三部分 API 时,它的锁没有被使用。
例如
class Syncer {
synchronized void foo(){}
}
...
Syncer s = new Syncer();
synchronize(s) {
...
}
// in another thread
s.foo() // oops, waiting for previous section, deadlocks potential
- 更不用说每个对象的命名空间污染(在 C# 中至少方法是静态的,在 Java 中同步原语必须使用
await
,不要重载wait
在Object
...)
不过,我确信这种设计是有原因的。内在锁的最大好处是什么?
最佳答案
You add extra cost for every object created, even though you'll actually use it only in a tiny fraction of the objects.
这是由 JVM 实现决定的。 JVM specification说,“监视器与对象的关联可以通过超出本规范范围的各种方式进行管理。例如,监视器可以与对象同时分配和释放。或者,它可以是动态的在线程试图获得对该对象的独占访问权时分配,并在稍后没有线程保留在该对象的监视器中时释放。”
我还没有看过太多的 JVM 源代码,但如果有任何常见的 JVM 能低效地处理这个问题,我会感到非常惊讶。
Lock usage become implicit, having lockMap.get(key).lock() is more readable than synchronization on arbitrary objects, eg, synchronize (key) {...}.
我完全不同意。一旦您了解了 synchronize
的含义,它就比一连串的方法调用更具可读性。
Synchronized methods can cause subtle error of users locking the object with the synchronized methods
这就是为什么您需要了解同步
的含义的原因。如果您了解它的作用,那么避免这些错误就变得相当微不足道了。经验法则:不要在多个地方使用同一个锁,除非这些地方需要共享同一个锁。任何语言的锁/互斥策略都可以这样说。
You can be sure that when passing an object to a 3rd parting API, it's lock is not being used.
没错。这通常是一件好事。如果它被锁定,应该有一个很好的理由来锁定它。其他线程(第三方或非第三方)需要等待。
如果您在 myObject
上进行同步,目的是允许其他线程同时使用 myObject
,那么您就错了。如果有帮助,您可以使用 myOtherObject
轻松地同步相同的代码块。
Not to mention the namespace polution for each and every object (in C# at least the methods are static, in Java synchronization primitives have to use await, not to overload wait in Object...)
Object
类确实包含一些与同步相关的便捷方法,即 notify()
、notifyAll()
和 wait ()
。您不需要使用它们的事实并不意味着它们没有用。您可以很容易地提示 clone()
、equals()
、toString()
等
关于c# - 为什么Java和C#要给每个对象都加上内在锁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20608494/