I asked 类似的问题 https://stackoverflow.com/questions/10548066/multiple-object-locks-in-java前几天,但对回复不满意,主要是因为我提供的代码存在一些人们关注的问题。
基本上,在 Java 中锁定私有成员的最佳实践是什么?假设每个私有字段只能单独操作,而不能一起操作(就像下面的 Test 类示例一样),您应该直接锁定每个私有字段(示例 1),还是应该为每个要锁定的私有字段使用通用锁定对象(示例2)?
示例1:直接锁定私有字段
class Test {
private final List<Object> xList = new ArrayList<Object>();
private final List<Object> yList = new ArrayList<Object>();
/* xList methods */
public void addToX(Object o) {
synchronized(xList) {
xList.add(o);
}
}
public void removeFromX(Object o) {
synchronized(xList) {
xList.remove(o);
}
}
/* yList methods */
public void addToY(Object o) {
synchronized(yList) {
yList.add(o);
}
}
public void removeFromY(Object o) {
synchronized(yList) {
yList.remove(o);
}
}
}
示例 2:为每个私有字段使用锁定对象
class Test {
private final Object xLock = new Object();
private final Object yLock = new Object();
private List<Object> xList = new ArrayList<Object>();
private List<Object> yList = new ArrayList<Object>();
/* xList methods */
public void addToX(Object o) {
synchronized(xLock) {
xList.add(o);
}
}
public void removeFromX(Object o) {
synchronized(xLock) {
xList.remove(o);
}
}
/* yList methods */
public void addToY(Object o) {
synchronized(yLock) {
yList.add(o);
}
}
public void removeFromY(Object o) {
synchronized(yLock) {
yList.remove(o);
}
}
}
我个人更喜欢第二种形式。没有其他代码at all可以使用该参考(禁止反射、调试 API 等)。您无需担心列表的内部详细信息是否尝试在其上同步。 (您在列表上调用的任何方法显然都可以访问this
,所以可以同步它。)purely使用它来锁定 - 所以你还可以分离“我是一把锁”和“我是一个列表”之间的关注点。
我发现这样更容易理解显示器,正如您可以轻松看到的all使用它的可能代码。
您可能希望创建一个单独的类,纯粹用作监视器,并覆盖toString()
这有助于诊断。它还将使变量的目的更加清晰。
诚然这种做法does占用更多内存,并且usually您无需担心代码锁定this
...但我个人认为分离关注点的好处是不必担心该代码是否does锁定本身超过了效率成本。如果您发现“浪费”的对象,您始终可以选择第一种形式are由于某种原因出现性能瓶颈(并且在分析了类中的代码后,您可能会同步)。
(我个人希望 Java 和 .NEThadn't沿着“每个对象都有一个关联的监视器”路线,但这是另一天的咆哮。)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)