它是安全/可以接受的做法来锁定一个私有字段变量(而不是使用的锁定对象)? 这样一来,我可以为不同的目的不同的锁。 实施例下面:
class Test {
private Integer x = 0;
private Integer y = 0;
public void incrementX() {
synchronized(x) {
x++;
}
}
public void decrementX() {
synchronized(x) {
x++;
}
}
public void incrementY() {
synchronized(y) {
y++;
}
}
public void decrementY() {
synchronized(y) {
y++;
}
}
或者我应该为每个私有成员我要锁定的锁定对象? 例:
class Test {
private final Object xLock = new Object();
private final Object yLock = new Object();
private Integer x = 0;
private Integer y = 0;
...
}
或者我应该有一个总的锁和使用,对于需要锁定所有的私有变量? 例:
class Test {
private final Object objLock = new Object();
private Integer x = 0;
private Integer y = 0;
...
}
小心始终使用最后一个成员VAR的锁! 如果您使用的Integer
,例如,你打算改变它,那将是非常糟糕的做法,因为每次调用将看到一个不同的对象,并导致数据争用。
无论您使用的一个或几个锁取决于你想要达到的协调方案,所以它完全特定领域。 你一定以为通过精心哪些操作,哪些不是相互排斥的,适当地分配锁给他们。 没有单一的最佳实践在这里。
如果你有你的对象在两个正交操作可能不会造成任何数据争同时发生,那是两把锁的情况。 在您的例子有两个整数,各自独立地改变。 我认为这是两个锁的情况。 如果你有更复杂的代码,其中在至少一个操作你需要访问两个整数,这将绑在一起,他们和那么你就需要一个单一的锁。
这是完全可以接受的锁定在一个私人的领域,只要这个领域是一个对象。 原语不具有内在的锁,而第一个片段因而无效。
不过,我想避免对私有字段锁定,如果该字段是从外部访问(使用一个getter,例如),因为这将允许任何人锁定为不同目的在同一对象上。 第二种解决方案是这样的最清洁,IMHO。
使用单锁是适得其反,因为它可以防止到这应该是能够同时运行方法的并发访问。 这是因此一般最好是有细粒度锁。
编辑:
现在你已经改变了你的问题,使用包装对象,在私人的Integer实例锁定真的不是一个很好的解决方案,因为你改变了方法里面,这些变量的值。 使用Final领域锁 。
请记住, x++
,如果x
是一个整数实例,就相当于:
int temp = x.intValue();
temp++;
x = Integer.valueOf(temp);
此外,由于Integer.valueOf()缓存整数的情况下,你可能会使用相同的整数实例来锁定完全不同的东西几类。 配方的执行速度慢和死锁。
我想你应该有两个字段两个不同的锁。 您锁定对象,以防止两个或多个线程访问同一个对象在同一时间。
您还可以看看Java中的锁定对象http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/Lock.html它比同步更高性能,并在java.util.concurrent中也有一些实用工具类锁的工作(也是ReadWriteLock中,如果需要的话)
据我所知,你使用锁定的对象仅仅是作为一个ID。 我的意思是,你可以使用任何你想要的对象。 唯一重要的事情是,“如果两件事情必须是相互排斥的,那么他们必须使用相同的锁”。
因此,使用自己的VAR的做法似乎确定。
但要记住!!
- 我不认为你可以在原始锁,它必须是一个
Object
- 如果您更改字段值,接下来的过程将获得一个不同的锁!
因此,单独锁似乎更安全。 除非你有绝对的把握你的领域是不会改变的(事实上,你应该把它声明为final
)。