获取字段访问权限的常用方法是同步getter和setter。使用int的简单示例如下所示:
private int foo = 0;
public synchronized int get(){return this.foo;}
public synchronized void set(int bar){ this.foo = bar;}
现在,虽然这是一种使访问线程安全的安全方法,但它也表明只有一个线程一次只能读取foo
。
如果很多线程经常阅读foo
,并且有时只更新这个变量,那将是一个很大的浪费。相反,getter可以被多个线程同时调用而没有任何问题。
是否有任何关于如何处理此问题的既定模式?或者你会如何以最优雅的方式解决这个问题?
答案 0 :(得分:5)
看看ReadWriteLock。这个界面是你正在寻找的,它允许多个读者,但只允许一个作家。
一个例子:
private int foo = 0;
private ReadWriteLock rwLock = /* use some implementation of ReadWriteLock here */;
public int get() {
Lock l = rwLock.readLock();
int result = 0;
l.lock();
try {
result = this.foo;
}
catch(Exception ex) {
// may throw the Exception here
}
finally {
l.unlock();
}
return result;
}
public void set(int bar){
Lock l = rwLock.writeLock();
l.lock();
try {
this.foo = bar;
}
catch(Exception ex) {
// may throw the Exception here
}
finally {
l.unlock();
}
}
答案 1 :(得分:3)
如果您只是设置并获取变量:那么您可以使用volatile
并删除synchronized
方法。
如果您对添加的整数进行任何操作,则应使用AtomicInteger
。
修改强>
如果存在多次读取字段并更新几次的情况,则会出现名为IMMUTABLE的模式。这是实现线程安全的方法之一。
class ImmutableClass{
private final int a;
public ImmutableClass(int a) {
this.a = a;
}
public int getA(){
return a;
}
/*
* No setter methods making it immutable and Thread safe
*/
}
有关不变性的更详细知识,Java Concurrency In practice是我建议您阅读的最佳资源。
更高级的方法:有Read/Write lock
答案 2 :(得分:0)
对于像你这样简单的例子,设置器中只有一个字段并且没有复杂的逻辑来真正要求互斥,你可以将字段声明为volatile
并删除{{1}关键字。
对于更复杂的东西,您可以使用廉价读写锁定模式:
synchronized