Commits

Anonymous committed a0abf76

[CACHE-60] Fixed a threading problem that could cause threads to block indefinitely. This only occurs on systems under high load and when a problem occurs during the building of a cache entry (ie, when cancelUpdate() is called).

  • Participants
  • Parent commits 27ab7d5

Comments (0)

Files changed (1)

File src/core/java/com/opensymphony/oscache/base/Cache.java

                 } else if (updateState.isUpdating()) {
                     // Another thread is already updating the cache. We block if this
                     // is a new entry, or blocking mode is enabled. Either putInCache()
-                    // or cancelRefresh() can cause this thread to resume.
+                    // or cancelUpdate() can cause this thread to resume.
                     if (cacheEntry.isNew() || blocking) {
                         do {
                             try {
                         } while (updateState.isUpdating());
 
                         if (updateState.isCancelled()) {
-                            // The updating thread cancelled the update, let this one have a go
+                            // The updating thread cancelled the update, let this one have a go.
                             updateState.startUpdate();
 
+                            // We put the updateState object back into the updateStates map so
+                            // any remaining threads waiting on this cache entry will be notified
+                            // once this thread has done its thing (either updated the cache or
+                            // cancelled the update). Without this code they'll get left hanging...
+                            synchronized (updateStates) {
+                                updateStates.put(key, updateState);
+                            }
+
                             if (cacheEntry.isNew()) {
                                 accessEventType = CacheMapAccessEventType.MISS;
                             } else {
                 if (state != null) {
                     synchronized (state) {
                         state.cancelUpdate();
-                        state.notifyAll();
+                        state.notify();
                     }
                 }
             }
 
     /**
      * Get the updating cache entry from the update map. If one is not found,
-     * create a new one and add it to the map.
+     * create a new one (with state {@link EntryUpdateState#NOT_YET_UPDATING})
+     * and add it to the map.
      *
      * @param key The cache key for this entry
      *