Java Synchronized如何比较锁定的对象?

Jas*_*son 5 java multithreading synchronization

我想在多个API请求上锁定一个对象,这样每个用户只能输入一个代码块.

是否synchronized(obj)基于对象的引用或它的锁定hashCode()功能?

我可以这样做:

synchronized("asdf") {
    doSomethingNifty();
}
Run Code Online (Sandbox Code Playgroud)

这里"asdf"有一个唯一的哈希,但没有唯一的引用.

Gra*_*ray 12

synchronized(obj)是否基于对象的内存位置或其toHash()函数进行锁定?

都不是.它锁定在与对象关联的监视器上.就JVM而言,我们不讨论对象的内存地址,因为它是可重定位的,并且它不是哈希代码(即使在方面Object.hashcode()),因为它不是唯一的.

就你应该锁定的内容而言,它应该是同一个final对象.就像是:

private final Object lockObject = new Object();
...
synchronized (lockObject) {
   // do stuff that needed to be protected
}
Run Code Online (Sandbox Code Playgroud)

您希望它final可以保证多个线程锁定在不更改的同一对象引用上. private很好,所以外面的类不能搞砸类内部的锁定.

这里"asdf"具有唯一的哈希,但没有唯一的内存地址.

"asdf"不能有一个唯一的哈希,因为其他字符串可能具有相同的哈希值,它实际上可以在应用程序中有一个独特的"内存地址"跨越"ASDF"的所有用法如果编译器将其存储在Java字符串池.这意味着一些完全不同的类也可能具有相同的坏模式代码块,并且会影响类的同步,因为它将锁定在同一个String对象实例上.这就是private锁定对象如此重要的原因.

虽然我们关于这个问题,还必须永远像一个非最终的物体,像可变值同步BooleanInteger.经常使用以下模式,这是非常错误的:

Boolean value = false;
...
// really bad idea
synchronized (value) {
   if (value) {
      value = false;
   } else {
      value = true;
   }
}
Run Code Online (Sandbox Code Playgroud)

这是非常错误的,因为value引用正在改变.因此,一个线程可能会锁定它,然后更改它的引用值,以便另一个线程将锁定另一个对象,并且两个线程将同时在其中synchronized.更糟糕的是因为Boolean只有2个值true而且false是常量,因此多个类将锁定在相同的引用上.