[英]Java uses object as monitor, isn't that object too heavy weight?
我是用Java语言规范17.1阅读的:
“ Java中的每个对象都与一个监视器关联,线程可以锁定或解锁监视器。”
为什么一定要这样? 这不是使Java对象太重吗? 我不知道为什么像字符串这样的对象自然应该是监视器!
编辑:
我想一想,是的,Java有一个关键字sync ,因为每个对象都可以有一个同步方法,因此有必要将每个对象与Monitor关联。
但这仍然不是一个很好的解决方案,通常一个类需要一个互斥量,除了pojo类非常简单之外。
您的假设中有一些道理,在经典著作“ Java Concurrency in Practice”(由权威专家Brian Goetz,Tim Peierls,Joshua Bloch,Joseph Bowbeer,David Holmes,Doug Lea撰写)中,他们写道:
每个对象都有内置锁的事实只是一种方便,因此您无需显式创建锁对象。 回想起来,这个设计决定可能是一个糟糕的决定:不仅会造成混乱,而且会迫使JVM实现者在对象大小和锁定性能之间进行权衡。
(第2.4章:带锁的防护状态)
您的基本问题是假设每个对象都内置有某种Monitor
,等待其被某些代码使用。 实际上,大多数对象从不用作监视器,因此在使用监视器之前不必创建它们。 与其将这个功能实现为每个具有private Monitor monitor
字段的HashMap<object, Monitor> monitors
不如将其视为具有全局HashMap<object, Monitor> monitors
的JVM来实现。
可能的实现方式是:每当输入synchronized
块时,JVM都会在映射( monitors
)中查找同步对象。 如果找到它,则可以使用监视器。 如果找不到,则会进入地图专用的关键部分。 然后,它再次查找该对象,因为在上一次检查和进入关键部分之间可能已经有另一个线程创建了该对象。 如果仍然不存在,它将为同步对象创建监视器,并离开关键部分。
这是使几乎所有线程安全的一种非常聪明的方法。 我认为沉重的体重有些主观; 在Java中,例如,对象只获得一项须予公布等待队列,同时指定互斥明确与完成synchronize
。
C#使用类似的方法来增强线程安全性,因此显然MS也认为这是一个非常聪明的解决方案。 替代是什么? 手写信号量和互斥量? 在Java中,考虑到大多数生产级应用程序(即服务器,服务等) 必须是多线程的,这将是一场噩梦。 让语言为您完成所有困难/无聊的工作真是太棒了。
线程同步对于确保正确的结果是必要的,因为它们可能处于竞争状态。
好吧,如果它不如LCD或CRT显示器那么重,那还好吗?
没那么重 对象很便宜。
我同意任何对象都可以是锁的概念非常令人困惑。 许多人认为, synchronized(obj)
可以防止同时访问obj
。 如果我们将锁与国家/地区分开,则这种误解的可能性较小。
Java内存模型中的文字不显示使用任意对象或任何对象作为同步原语的任何重要性。 为此目的使用对象也许是一种经济的设计。
它也可以将整数用作锁。 synchronized(493725)
实际上是因为每个对象在内部都与一个整数(其地址)相关联,因此JVM可能synchronized(493725)
。 未同步的对象的开销为零。
使用java.util.concurrent类,即使您不喜欢它,也不再需要此类synchronized(obj)
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.