c# - 为什么Java和C#要给每个对象都加上内在锁?

标签 c# java synchronization locking

让每个对象都可锁定看起来像是一个设计错误:

  1. 您为创建的每个对象都增加了额外成本,即使您实际上只会在一小部分对象中使用它。
  2. 锁的使用变得隐式,lockMap.get(key).lock() 比任意对象上的同步更具可读性,例如,synchronize (key) {...}/
  3. 同步方法可能导致用户使用同步方法锁定对象的细微错误
  4. 您可以确定将对象传递给第三部分 API 时,它的锁没有被使用。

例如

class Syncer {
    synchronized void foo(){}
}
...
Syncer s = new Syncer();
synchronize(s) {
    ...
}
// in another thread
s.foo() // oops, waiting for previous section, deadlocks potential
  1. 更不用说每个对象的命名空间污染(在 C# 中至少方法是静态的,在 Java 中同步原语必须使用 await,不要重载 waitObject...)

不过,我确信这种设计是有原因的。内在锁的最大好处是什么?

最佳答案

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/

相关文章:

java - getClass().getName() 什么时候返回 void?

java - 如何将文本文件中的文本字符串替换为用户输入中的 ArrayList

java - OpenNLP Namefinder API 中的自定义特征生成

python - 如何在Python中将变量与多个进程同步?

Java:何时同步方法和 block

c# - 谁应该记录错误/异常

c# - 不调用 Thread.Join() 的后果

c# - 如何在 C# XNA 中创建 Wait() 方法?

c# - 将百分比转换为最接近的分数

java - 我不明白同步在我的代码中是如何工作的