使每个对象可锁定看起来像是一个设计错误:
lockMap.get(key).lock()
比任意对象上的同步更具可读性,例如synchronize (key) {...}
。例如
class Syncer {
synchronized void foo(){}
}
...
Syncer s = new Syncer();
synchronize(s) {
...
}
// in another thread
s.foo() // oops, waiting for previous section, deadlocks potential
await
,而不是在wait
中重载Object
} ...)但是我确信这个设计有一些原因。内在锁的好处是什么?
答案 0 :(得分:1)
您为每个创建的对象添加了额外的费用,即使您已经开始 实际上只在一小部分物体中使用它。
由JVM实现决定。 JVM specification表示,"监视器与对象的关联可以通过超出本规范范围的各种方式进行管理。例如,可以与对象同时分配和释放监视器。或者,它可以在线程尝试获得对对象的独占访问时动态分配,并在稍后当监视器中没有剩余线程保留该对象时释放。"
我还没有查看过很多JVM源代码,但如果任何常见的JVM处理这种效率低下,我会感到非常惊讶。
锁定用法变得隐含,具有lockMap.get(key).lock()更多 比任意对象上的同步更可读,例如,同步 (关键){...}。
我完全不同意。一旦你知道synchronize
的含义,它就比一系列方法调用更具可读性。
同步方法可能会导致用户锁定的细微错误 具有同步方法的对象
这就是为什么你需要知道synchronize
的含义。如果你读到它的作用,那么避免这些错误变得相当微不足道。经验法则:不要在多个地方使用相同的锁,除非这些地方需要共享同一个锁。任何语言的锁定/互斥策略都可以说同样的事情。
您可以确定在将对象传递给第3个分离API时,它是可以的 没有使用锁。
右。这通常是一件好事。如果它被锁定,应该有一个很好的理由来锁定它。其他线程(第三方与否)需要等待轮到他们。
如果您在myObject
上进行同步,目的是允许其他线程同时使用myObject
,那么您做错了。您可以使用myOtherObject
轻松同步相同的代码块,如果这样做有帮助的话。
更不用说每个对象的名称空间污染(在C#中 在Java同步原语中,至少方法是静态的 必须使用await,而不是在Object中重载等待...)
Object
类确实包含一些与同步相关的便捷方法,即notify()
,notifyAll()
和wait()
。你不需要使用它们的事实并不意味着它们不是很有用。你可以轻易抱怨clone()
,equals()
,toString()
等。
答案 1 :(得分:0)
实际上你只在每个对象中引用了那个监视器;只有在使用synchronization =>时才会创建真正的监视器对象。没有那么多的记忆丢失了。
另一种方法是将手动监视器添加到您需要的那些类中;这会使代码复杂化并且更容易出错。 Java已经将性能换成了生产力。
答案 2 :(得分:0)
一个好处是退出synchronized
块时自动解锁,即使是异常。
答案 3 :(得分:0)
我认为像toString()一样,设计师认为好处超过了成本。
必须做出很多决定并且很多概念都未经过测试(Checked exceptions-ack!)但总的来说,我确信它比显式的“Lock”对象更自由,更有用。
您还在语言或库中添加“Lock”对象吗?看起来像一个语言结构,但库中的对象很少(如果有的话)有特殊处理,但是将线程作为一个库构造更多地处理可能会减慢速度。