我想通过多个 API 请求锁定一个对象,这样每个用户只有一个请求可以输入一段代码。
synchronized(obj)
是否基于对象的引用或其 hashCode()
函数进行锁定?
即我能做吗:
synchronized("asdf") {
doSomethingNifty();
}
这里“asdf”有一个唯一的散列但没有唯一的引用。
最佳答案
Does synchronized(obj) lock based on the object's memory location or its toHash() function?
都没有。它锁定与对象关联的监视器。就 JVM 而言,我们不讨论对象的内存地址,因为它是可重定位的,而且它不是哈希码(即使在 Object.hashcode()
方面),因为它不是唯一的。
就您应该 锁定的内容而言,它应该是相同的 final
对象。像这样的东西:
private final Object lockObject = new Object();
...
synchronized (lockObject) {
// do stuff that needed to be protected
}
您希望它是final
以便可以保证多个线程锁定在同一个未更改的对象引用上。 private
很好,因此外部类不能搞砸类内部的锁定。
Here "asdf" has a unique hash but no unique memory address.
“asdf”
不有一个唯一的散列,因为其他字符串可能有相同的散列,它实际上可能有一个唯一的“内存”如果编译器将它存储在 Java string pool 中,则应用程序中所有使用“asdf”的地址” .这意味着一些完全不同的类也可能具有相同的错误模式代码块,并且会影响您的类的同步,因为它会锁定在相同的 String
对象实例上。这就是为什么 private
锁对象如此重要。
当我们讨论这个主题时,您也绝不能同步可变值,例如 Boolean
或 Integer
等非最终对象。下面的模式经常被使用并且是非常错误的:
Boolean value = false;
...
// really bad idea
synchronized (value) {
if (value) {
value = false;
} else {
value = true;
}
}
这是非常错误,因为value
引用正在改变。所以一个线程可能会锁定它,然后更改它的引用值,这样另一个线程会锁定另一个对象,并且两个线程会同时在 synchronized
中。更糟糕的是,对于 Boolean
,只有 true
和 false
这两个值是常量,因此多个类将锁定相同的引用。
关于java - Java Synchronized 如何比较锁定的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16675005/