diff --git a/lucene/contrib/misc/src/java/org/apache/lucene/search/SearcherManager.java b/lucene/contrib/misc/src/java/org/apache/lucene/search/SearcherManager.java
index 8222d09..50bf72a 100644
--- a/lucene/contrib/misc/src/java/org/apache/lucene/search/SearcherManager.java
+++ b/lucene/contrib/misc/src/java/org/apache/lucene/search/SearcherManager.java
@@ -21,6 +21,7 @@ import java.io.Closeable;
 import java.io.IOException;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Semaphore;
+import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
 
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexWriter;
@@ -64,10 +65,12 @@ import org.apache.lucene.store.Directory;
 
 public class SearcherManager implements Closeable {
 
+  final AtomicReferenceFieldUpdater<SearcherManager, IndexSearcher> searcherUpdater = AtomicReferenceFieldUpdater
+  .newUpdater(SearcherManager.class, IndexSearcher.class, "currentSearcher");
   // Current searcher
   private volatile IndexSearcher currentSearcher;
   private final SearcherWarmer warmer;
-  private final Semaphore reopening = new Semaphore(1);
+  private final Semaphore reopening = new Semaphore(1); // only one concurrent reopen
   private final ExecutorService es;
 
   /** Opens an initial searcher from the Directory.
@@ -152,7 +155,12 @@ public class SearcherManager implements Closeable {
               }
             }
           }
-          swapSearcher(newSearcher);
+          if (!trySwapSearcher(newSearcher)) {
+            // in this case we have been closed so lets release the just opened searcher
+            assert currentSearcher == null;
+            release(newSearcher);
+            throw new AlreadyClosedException("this SearcherManager is closed");
+          }
           return true;
         } else {
           return false;
@@ -188,15 +196,20 @@ public class SearcherManager implements Closeable {
     searcher.getIndexReader().decRef();
   }
 
-  // Replaces old searcher with new one - needs to be synced to make close() work
-  private synchronized void swapSearcher(IndexSearcher newSearcher)
+  // Replaces old searcher with new one
+  private boolean trySwapSearcher(IndexSearcher newSearcher)
     throws IOException {
-    IndexSearcher oldSearcher = currentSearcher;
-    if (oldSearcher == null) {
-      throw new AlreadyClosedException("this SearcherManager is closed");
+    final IndexSearcher toReplace = currentSearcher;
+    if (toReplace == null) {
+      return false;
     }
-    currentSearcher = newSearcher;
-    release(oldSearcher);
+    if (searcherUpdater.compareAndSet(this, toReplace, newSearcher)) {
+      if (toReplace != null) {
+        release(toReplace);
+      }
+      return true;
+    }
+    return false;
   }
 
   /** Close this SearcherManager to future searching.  Any
@@ -205,6 +218,9 @@ public class SearcherManager implements Closeable {
    *  after they are done. */
   @Override
   public void close() throws IOException {
-    swapSearcher(null);
+    while(currentSearcher != null) {
+      trySwapSearcher(null);  
+    }
+    
   }
 }
diff --git a/lucene/contrib/misc/src/test/org/apache/lucene/search/TestSearcherManager.java b/lucene/contrib/misc/src/test/org/apache/lucene/search/TestSearcherManager.java
index 3a7c99b..d60ba36 100644
--- a/lucene/contrib/misc/src/test/org/apache/lucene/search/TestSearcherManager.java
+++ b/lucene/contrib/misc/src/test/org/apache/lucene/search/TestSearcherManager.java
@@ -18,10 +18,17 @@ package org.apache.lucene.search;
  */
 
 import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutorService;
+import java.util.concurrent.atomic.AtomicBoolean;
 
+import org.apache.lucene.analysis.MockAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.ThreadedIndexingAndSearchingTestCase;
+import org.apache.lucene.store.AlreadyClosedException;
+import org.apache.lucene.store.Directory;
 import org.apache.lucene.util._TestUtil;
 
 public class TestSearcherManager extends ThreadedIndexingAndSearchingTestCase {
@@ -110,4 +117,74 @@ public class TestSearcherManager extends ThreadedIndexingAndSearchingTestCase {
     }
     mgr.close();
   }
+  
+  public void testIntermediateClose() throws IOException, InterruptedException {
+    Directory dir = newDirectory();
+    IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig(
+        TEST_VERSION_CURRENT, new MockAnalyzer(random)));
+    writer.addDocument(new Document());
+    writer.commit();
+    final CountDownLatch awaitEnterWarm = new CountDownLatch(1);
+    final CountDownLatch awaitClose = new CountDownLatch(1);
+
+    final SearcherManager searcherManager = new SearcherManager(dir,
+        new SearcherWarmer() {
+          @Override
+          public void warm(IndexSearcher s) throws IOException {
+            try {
+              awaitEnterWarm.countDown();
+              awaitClose.await();
+            } catch (InterruptedException e) {
+              //
+            }
+          }
+        });
+    IndexSearcher searcher = searcherManager.acquire();
+    try {
+      assertEquals(1, searcher.getIndexReader().numDocs());
+    } finally {
+      searcherManager.release(searcher);
+    }
+    writer.addDocument(new Document());
+    writer.commit();
+    final AtomicBoolean success = new AtomicBoolean(false);
+    final AtomicBoolean triedReopen = new AtomicBoolean(false);
+    final Throwable[] exc = new Throwable[1];
+    Thread thread = new Thread(new Runnable() {
+      @Override
+      public void run() {
+        try {
+          triedReopen.set(true);
+          searcherManager.maybeReopen();
+          success.set(true);
+        } catch (AlreadyClosedException e) {
+          // expected
+        } catch (Throwable e) {
+          exc[0] = e;
+          // use success as the barrier here to make sure we see the write
+          success.set(false);
+
+        }
+      }
+    });
+    thread.start();
+    awaitEnterWarm.await();
+    for (int i = 0; i < 2; i++) {
+      searcherManager.close();
+    }
+    awaitClose.countDown();
+    thread.join();
+    try {
+      searcherManager.acquire();
+      fail("already closed");
+    } catch (AlreadyClosedException ex) {
+      // expected
+    }
+    assertFalse(success.get());
+    assertTrue(triedReopen.get());
+    assertNull("" + exc[0], exc[0]);
+    writer.close();
+    dir.close();
+
+  }
 }
