title: Is this implementation of memoized computation correct?
body: <p>I needed to implement a simple generic wrapper for computation memoization, with ability to reset the memoized value on demand. Computation is potentially long-running, and so reset shouldn't block for too long - ideally, it just marks the current state as "dirty" and returns.</p>
  
  <p>Here's what I did:</p>
  
  <pre><code>import java.util.concurrent.Callable;
  import java.util.concurrent.locks.Lock;
  import java.util.concurrent.locks.ReentrantLock;
  
  public class CachedValue&lt;A&gt; {
      private Callable&lt;A&gt; creator;
      private Lock computationLock = new ReentrantLock();
      private Lock resultLock = new ReentrantLock();
      private volatile A cached = null;
      private volatile boolean wasCleared = false;
  
      public CachedValue(Callable&lt;A&gt; 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();
          }
      }
  }
  </code></pre>
  
  <p>It seems to work, but I'm no expect in parallel programming, so I maybe I missed some deadlock or efficiency issues?</p>