对不起我的英语
我不使用任何字段进行锁定,因为所以我不应该考虑某些字段是否可以具有值 null
。
我总是创建仅用于线程同步锁定的特殊字段。
例如:
public class Worker {
private static final List<Toilet> TOILETS = Arrays.asList(
new Toilet(1),
new Toilet(2),
// ...
new Toilet(NUMBER_OF_FLOORS)
);
// here it is:
private static final List<String> LOCK_TOILETS = Arrays.asList(
"LOCK TOILET #1",
"LOCK TOILET #2",
// ...
"LOCK TOILET #" + NUMBER_OF_FLOORS
);
private final int floorNumber;
public void spendWorkingHours() {
for (int i = 0; i < X; ++i) {
doWork();
snackSomething();
String lockToilet = LOCK_TOILETS.get(floorNumber);
Toilet theOnlyToiletOnTheFloor = TOILETS.get(floorNumber);
synchronized (lockToilet) {
goToToilet(theOnlyToiletOnTheFloor);
}
}
}
}
最佳答案
您不应该使用String
来锁定对象,尤其是字符串文字。
字符串文字来自于String
池,并且相同字符串的每个String
文字都是相同引用。这意味着如果两个不同的线程使用两个“不同”的字符串文字实际上是相同的,因此很容易发生死锁。
演示:
// Thread #1
String LOCK1 = "mylock";
synchronized (LOCK1) {
}
// Thread #2
String LOCK2 = "mylock";
synchronized (LOCK2) {
// This is actually the SAME lock,
// might cause deadlock between the 2 synchronized blocks!
// Because LOCK1==LOCK2!
}
最好是同步无法从“外部”访问的私有(private)对象。如果您使用从“外部”可见(或由方法返回)的 Object
锁,则任何人都可以将该对象用作您无法控制的锁,并且可能会导致与您的内部synchronized
block 发生死锁。
例如,您可以同步想要保护的对象(如果它是私有(private)的),或者创建一个私有(private)的内部锁Object
:
private final Object LOCK = new Object();
// Later:
synchronized (LOCK) {
// LOCK is not known to any "outsiders", safe to use it as internal lock
}
关于java - 创建和使用 String 对象来锁定线程同步是一个好习惯吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25863255/