这种记忆计算的实现是否正确?
Is this implementation of memoized computation correct?
我需要为计算记忆实现一个简单的通用包装器,能够根据需要重置记忆值。计算可能很长 - 运行,因此重置不应阻塞太久 - 理想情况下,它只是将当前状态标记为 "dirty" 和 returns.
这是我所做的:
import java.util.concurrent.Callable;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class CachedValue<A> {
private Callable<A> creator;
private Lock computationLock = new ReentrantLock();
private Lock resultLock = new ReentrantLock();
private volatile A cached = null;
private volatile boolean wasCleared = false;
public CachedValue(Callable<A> creator) {
this.creator = creator;
}
public A get() {
if (cached != null) {
return cached;
} else {
computationLock.lock();
try {
if (cached != null) {
return cached;
} else {
while (true) {
wasCleared = false;
A computed = creator.call();
resultLock.lock();
try {
if (!wasCleared) {
cached = computed;
return cached;
}
} finally {
resultLock.unlock();
}
}
}
} finally {
computationLock.unlock();
}
}
}
public void reset() {
resultLock.lock();
try {
cached = null;
wasCleared = true;
} finally {
resultLock.unlock();
}
}
}
它似乎有效,但我对并行编程没有期望,所以我可能错过了一些死锁或效率问题?
您必须保护 cached
和 wasCleared
变量,因为可以使用一个线程的 reset
方法重置这些变量,而另一个线程调用 get
方法会处理同一组变量。
您可以在重置方法中使用相同的可重入锁:
public void reset() {
lock.lock();
try {
cached = null;
wasCleared = true;
} finally {
lock.unlock();
}
}
我需要为计算记忆实现一个简单的通用包装器,能够根据需要重置记忆值。计算可能很长 - 运行,因此重置不应阻塞太久 - 理想情况下,它只是将当前状态标记为 "dirty" 和 returns.
这是我所做的:
import java.util.concurrent.Callable;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class CachedValue<A> {
private Callable<A> creator;
private Lock computationLock = new ReentrantLock();
private Lock resultLock = new ReentrantLock();
private volatile A cached = null;
private volatile boolean wasCleared = false;
public CachedValue(Callable<A> creator) {
this.creator = creator;
}
public A get() {
if (cached != null) {
return cached;
} else {
computationLock.lock();
try {
if (cached != null) {
return cached;
} else {
while (true) {
wasCleared = false;
A computed = creator.call();
resultLock.lock();
try {
if (!wasCleared) {
cached = computed;
return cached;
}
} finally {
resultLock.unlock();
}
}
}
} finally {
computationLock.unlock();
}
}
}
public void reset() {
resultLock.lock();
try {
cached = null;
wasCleared = true;
} finally {
resultLock.unlock();
}
}
}
它似乎有效,但我对并行编程没有期望,所以我可能错过了一些死锁或效率问题?
您必须保护 cached
和 wasCleared
变量,因为可以使用一个线程的 reset
方法重置这些变量,而另一个线程调用 get
方法会处理同一组变量。
您可以在重置方法中使用相同的可重入锁:
public void reset() {
lock.lock();
try {
cached = null;
wasCleared = true;
} finally {
lock.unlock();
}
}