抱歉我的英文
我没有使用任何字段进行锁定,因此我不应该考虑某些字段是否有值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);
}
}
}
}
答案 0 :(得分:6)
您不应将String
用于锁定对象,尤其不应使用字符串文字。
字符串文字来自String
池,每个String
文字是相同的字符串,是相同的引用。这意味着如果2个不同的线程使用2&#34;不同的&#34;字符串文字实际上是相同的,因此很容易发生死锁。
演示:
// 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!
}
最好是在&#34;外部&#34;上无法访问的私有对象上进行同步。如果您使用Object
锁定,可以从&#34;外部&#34; (或通过方法返回),任何人都可以使用该对象作为您无法控制的锁,并可能导致内部synchronized
块死锁。
例如,如果它是私有的,你可以同步你要保护的对象,或者创建一个私有的内部锁Object
:
private final Object LOCK = new Object();
// Later:
synchronized (LOCK) {
// LOCK is not known to any "outsiders", safe to use it as internal lock
}
答案 1 :(得分:1)
使用String
可能不是最好的主意,因为这个类得到了一些特殊处理,并且可以重复使用具有相同内容的字符串(因此在一楼锁上厕所也会锁定厕所在其他楼层使用相同的号码。)
这里你最好的选择是锁上实际的马桶。
答案 2 :(得分:1)
lockToilet
为什么不在每个TOILET
资源上使用synchronized statement?
Toilet t;
syncrhonized(TOILETS)
{
t = = TOILETS.get(floorNumber);
}
synchronized (t) {
goToToilet(t);
}
syncrhonized
在这段代码中,对括号内对象的任何使用都是在brakets范围内的线程排他性,因此这个对象变成了一个锁。
答案 3 :(得分:1)
答案确实涵盖了关于使用字符串进行锁定的问题(有关详细信息,请参阅字符串实习),因此我将仅提及其他一些注意事项:
虽然您已将List
定义为final
(无法指定其他列表实例)并使用.asList(..)
进行初始化(无法更改大小),但这并不是只读或thread-safe
,所以如果有人更改了该列表中的元素,您可能会进入不稳定状态。考虑使用只读列表。
您还需要澄清锁定范围。你想锁定什么?如果goToToilet
更改了对象属性,那么同步点将更好地放置在更改Object
状态的方法中。 (这是一个设计建议;代码可以工作,但在将来更改代码时也容易出错)
最后,我还将介绍java concurrent
结构,因为您可能会发现并发集合和锁定机制很有用。