给出以下代码:
public class SomeClass {
private boolean shouldBlock = false;
private Object resource;
public void handleDrawRequest(Canvas canvas) {
if (!shouldBlock && resource == null)
{
shouldBlock = true;
loadTheResource(); //which takes awhile
shouldBlock = false;
}
else if (shouldBlock && resrouce == null)
{
return; //another thread is taking care of the loading of the resource
//and its not ready yet, so just ignore this request
}
drawResourceOn(canvas);
}
}
如何使此代码线程安全?我正在尝试完成的是一个且只有一个线程加载资源,而同时尝试访问此代码的任何其他线程被丢弃(例如,遵循'else if'逻辑),直到资源被加载。可能有许多线程试图同时访问此代码,我不想同步整个方法并且整个堆栈的线程堆积起来。
答案 0 :(得分:4)
double checked non-blocking锁定:
public class SomeClass {
private Lock lock = new Lock();
private volatile Object resource;
public void handleDrawRequest(Canvas canvas) {
if( resource==null ) {
if( lock.tryLock() ) {
try {
if( resource==null )
resource = loadResource();
}
finally {
lock.unlock();
}
}
else {
return;
}
}
drawResourceOn(canvas);
}
}
如果你没有resource
volatile
,线程可以自由地缓存它,并且可能永远不会读取更新的值。特别是,第二个空检查将始终返回true,即使资源已在第一个之后加载。
答案 1 :(得分:2)
您正在寻找AtomicBoolean
public class SomeClass {
// AtomicBolean defaults to the value false.
private AtomicBoolean loadingResource = new AtomicBoolean();
private volatile Object resource;
public void handleDrawRequest(Canvas canvas) {
if (resource == null) {
if (loadingResource.compareAndSet(false, true)) {
loadTheResource(); //which takes awhile
} else {
//another thread is taking care of the loading of the resource
//and its not ready yet, so just ignore this request
return;
}
} else {
drawResourceOn(canvas);
}
}
}