You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucenenet.apache.org by ni...@apache.org on 2021/10/17 15:55:49 UTC

[lucenenet] 04/08: SWEEP: Lucene.Net: Changed all lock statements to UninterruptableMonitor.Enter and UninterruptableMonitor.Exit to prevent ThreadInterruptedException from occurring when entering a lock.

This is an automated email from the ASF dual-hosted git repository.

nightowl888 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/lucenenet.git

commit 19cb0c1d806462aad2b6297e0885491062887456
Author: Shad Storhaug <sh...@shadstorhaug.com>
AuthorDate: Thu Oct 14 20:41:49 2021 +0700

    SWEEP: Lucene.Net: Changed all lock statements to UninterruptableMonitor.Enter and UninterruptableMonitor.Exit to prevent ThreadInterruptedException from occurring when entering a lock.
---
 src/Lucene.Net.Tests/Index/TestIndexWriter.cs      |   2 +
 src/Lucene.Net/Codecs/Lucene3x/Lucene3xFields.cs   |   8 +-
 .../Codecs/Lucene3x/Lucene3xNormsProducer.cs       |  15 +-
 .../Codecs/Lucene40/Lucene40DocValuesReader.cs     |  22 +-
 .../Codecs/Lucene42/Lucene42DocValuesProducer.cs   |  29 +-
 .../Codecs/Lucene45/Lucene45DocValuesProducer.cs   |  22 +-
 src/Lucene.Net/Index/BufferedUpdatesStream.cs      |  57 +-
 src/Lucene.Net/Index/ConcurrentMergeScheduler.cs   | 100 ++-
 src/Lucene.Net/Index/DocumentsWriter.cs            |  66 +-
 .../Index/DocumentsWriterFlushControl.cs           | 163 ++++-
 src/Lucene.Net/Index/DocumentsWriterFlushQueue.cs  |  59 +-
 .../Index/DocumentsWriterPerThreadPool.cs          |  32 +-
 .../Index/DocumentsWriterStallControl.cs           |  40 +-
 src/Lucene.Net/Index/FieldInfos.cs                 |  36 +-
 src/Lucene.Net/Index/FlushPolicy.cs                |   8 +-
 src/Lucene.Net/Index/IndexFileDeleter.cs           |   5 +-
 src/Lucene.Net/Index/IndexReader.cs                |  32 +-
 src/Lucene.Net/Index/IndexWriter.cs                | 756 +++++++++++++++++----
 src/Lucene.Net/Index/MergePolicy.cs                |  56 +-
 src/Lucene.Net/Index/MultiReader.cs                |  10 +-
 src/Lucene.Net/Index/ParallelAtomicReader.cs       |   8 +-
 src/Lucene.Net/Index/ParallelCompositeReader.cs    |   8 +-
 .../Index/PersistentSnapshotDeletionPolicy.cs      |  43 +-
 src/Lucene.Net/Index/ReadersAndUpdates.cs          | 127 +++-
 src/Lucene.Net/Index/SegmentCoreReaders.cs         |  10 +-
 src/Lucene.Net/Index/SegmentDocValues.cs           |  22 +-
 src/Lucene.Net/Index/SerialMergeScheduler.cs       |   8 +-
 src/Lucene.Net/Index/SlowCompositeReaderWrapper.cs |  17 +-
 src/Lucene.Net/Index/SnapshotDeletionPolicy.cs     |  71 +-
 src/Lucene.Net/Index/StoredFieldsProcessor.cs      |  10 +-
 src/Lucene.Net/Index/TermsEnum.cs                  |  10 +-
 src/Lucene.Net/Search/CachingWrapperFilter.cs      |  10 +-
 .../Search/ControlledRealTimeReopenThread.cs       |  26 +-
 src/Lucene.Net/Search/FieldCacheImpl.cs            |  66 +-
 src/Lucene.Net/Search/ReferenceManager.cs          |  14 +-
 src/Lucene.Net/Search/SearcherLifetimeManager.cs   |  22 +-
 src/Lucene.Net/Search/TimeLimitingCollector.cs     |   1 +
 src/Lucene.Net/Store/CompoundFileDirectory.cs      |  15 +-
 src/Lucene.Net/Store/CompoundFileWriter.cs         |   8 +-
 src/Lucene.Net/Store/Lock.cs                       |   3 +-
 src/Lucene.Net/Store/LockVerifyServer.cs           |   8 +-
 src/Lucene.Net/Store/NRTCachingDirectory.cs        |  57 +-
 src/Lucene.Net/Store/NativeFSLockFactory.cs        | 109 ++-
 src/Lucene.Net/Store/RAMFile.cs                    |  43 +-
 src/Lucene.Net/Store/RateLimiter.cs                |   1 +
 src/Lucene.Net/Store/SimpleFSDirectory.cs          |   8 +-
 src/Lucene.Net/Store/SingleInstanceLockFactory.cs  |  29 +-
 src/Lucene.Net/Store/VerifyingLockFactory.cs       |  36 +-
 .../Support/Codecs/DefaultCodecFactory.cs          |  24 +-
 .../Codecs/DefaultDocValuesFormatFactory.cs        |  24 +-
 .../Support/Codecs/DefaultPostingsFormatFactory.cs |  24 +-
 src/Lucene.Net/Support/ConcurrentHashSet.cs        |  17 +-
 src/Lucene.Net/Support/ConcurrentSet.cs            | 193 +++++-
 src/Lucene.Net/Support/IO/StreamExtensions.cs      |   8 +-
 .../LimitedConcurrencyLevelTaskScheduler.cs        |  30 +-
 src/Lucene.Net/Support/Threading/ReentrantLock.cs  |   8 +-
 src/Lucene.Net/Util/AttributeSource.cs             |   8 +-
 src/Lucene.Net/Util/Fst/Util.cs                    |  15 +-
 src/Lucene.Net/Util/InfoStream.cs                  |  15 +-
 59 files changed, 2267 insertions(+), 407 deletions(-)

diff --git a/src/Lucene.Net.Tests/Index/TestIndexWriter.cs b/src/Lucene.Net.Tests/Index/TestIndexWriter.cs
index ce37594..56ade97 100644
--- a/src/Lucene.Net.Tests/Index/TestIndexWriter.cs
+++ b/src/Lucene.Net.Tests/Index/TestIndexWriter.cs
@@ -10,6 +10,7 @@ using Lucene.Net.Documents;
 using Lucene.Net.Index.Extensions;
 using Lucene.Net.Search;
 using Lucene.Net.Support;
+using Lucene.Net.Support.Threading;
 using Lucene.Net.Util;
 using NUnit.Framework;
 using RandomizedTesting.Generators;
@@ -1387,6 +1388,7 @@ namespace Lucene.Net.Index
                     // clear interrupt state:
                     try
                     {
+                        UninterruptableMonitor.RestoreInterrupt();
                         Thread.Sleep(0);
                     }
                     catch (Exception ie) when (ie.IsInterruptedException())
diff --git a/src/Lucene.Net/Codecs/Lucene3x/Lucene3xFields.cs b/src/Lucene.Net/Codecs/Lucene3x/Lucene3xFields.cs
index 68a210d..215d488 100644
--- a/src/Lucene.Net/Codecs/Lucene3x/Lucene3xFields.cs
+++ b/src/Lucene.Net/Codecs/Lucene3x/Lucene3xFields.cs
@@ -1,6 +1,7 @@
 using J2N.Text;
 using Lucene.Net.Diagnostics;
 using Lucene.Net.Index;
+using Lucene.Net.Support.Threading;
 using Lucene.Net.Util;
 using System;
 using System.Collections.Generic;
@@ -176,7 +177,8 @@ namespace Lucene.Net.Codecs.Lucene3x
         {
             get
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     if (Tis != null)
                     {
@@ -187,6 +189,10 @@ namespace Lucene.Net.Codecs.Lucene3x
                         return TisNoIndex;
                     }
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
diff --git a/src/Lucene.Net/Codecs/Lucene3x/Lucene3xNormsProducer.cs b/src/Lucene.Net/Codecs/Lucene3x/Lucene3xNormsProducer.cs
index b5e4792..08a3359 100644
--- a/src/Lucene.Net/Codecs/Lucene3x/Lucene3xNormsProducer.cs
+++ b/src/Lucene.Net/Codecs/Lucene3x/Lucene3xNormsProducer.cs
@@ -1,6 +1,7 @@
 using J2N.Runtime.CompilerServices;
 using J2N.Threading.Atomic;
 using Lucene.Net.Diagnostics;
+using Lucene.Net.Support.Threading;
 using System;
 using System.Collections.Generic;
 using System.Globalization;
@@ -217,17 +218,23 @@ namespace Lucene.Net.Codecs.Lucene3x
             {
                 get
                 {
-                    lock (this)
+                    UninterruptableMonitor.Enter(this);
+                    try
                     {
                         if (instance == null)
                         {
                             var bytes = new byte[outerInstance.maxdoc];
                             // some norms share fds
-                            lock (file)
+                            UninterruptableMonitor.Enter(file);
+                            try
                             {
                                 file.Seek(offset);
                                 file.ReadBytes(bytes, 0, bytes.Length, false);
                             }
+                            finally
+                            {
+                                UninterruptableMonitor.Exit(file);
+                            }
                             // we are done with this file
                             if (file != outerInstance.singleNormStream)
                             {
@@ -239,6 +246,10 @@ namespace Lucene.Net.Codecs.Lucene3x
                         }
                         return instance;
                     }
+                    finally
+                    {
+                        UninterruptableMonitor.Exit(this);
+                    }
                 }
             }
 
diff --git a/src/Lucene.Net/Codecs/Lucene40/Lucene40DocValuesReader.cs b/src/Lucene.Net/Codecs/Lucene40/Lucene40DocValuesReader.cs
index 55b1a7a..d43765d 100644
--- a/src/Lucene.Net/Codecs/Lucene40/Lucene40DocValuesReader.cs
+++ b/src/Lucene.Net/Codecs/Lucene40/Lucene40DocValuesReader.cs
@@ -1,5 +1,6 @@
 using J2N.Threading.Atomic;
 using Lucene.Net.Diagnostics;
+using Lucene.Net.Support.Threading;
 using System;
 using System.Collections.Generic;
 using System.Globalization;
@@ -74,7 +75,8 @@ namespace Lucene.Net.Codecs.Lucene40
 
         public override NumericDocValues GetNumeric(FieldInfo field)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (!numericInstances.TryGetValue(field.Number, out NumericDocValues instance))
                 {
@@ -138,6 +140,10 @@ namespace Lucene.Net.Codecs.Lucene40
                 }
                 return instance;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -431,7 +437,8 @@ namespace Lucene.Net.Codecs.Lucene40
 
         public override BinaryDocValues GetBinary(FieldInfo field)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (!binaryInstances.TryGetValue(field.Number, out BinaryDocValues instance))
                 {
@@ -461,6 +468,10 @@ namespace Lucene.Net.Codecs.Lucene40
                 }
                 return instance;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         private BinaryDocValues LoadBytesFixedStraight(FieldInfo field)
@@ -699,7 +710,8 @@ namespace Lucene.Net.Codecs.Lucene40
 
         public override SortedDocValues GetSorted(FieldInfo field)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (!sortedInstances.TryGetValue(field.Number, out SortedDocValues instance))
                 {
@@ -747,6 +759,10 @@ namespace Lucene.Net.Codecs.Lucene40
                 }
                 return instance;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         private SortedDocValues LoadBytesFixedSorted(/*FieldInfo field, // LUCENENET: Never read */ IndexInput data, IndexInput index)
diff --git a/src/Lucene.Net/Codecs/Lucene42/Lucene42DocValuesProducer.cs b/src/Lucene.Net/Codecs/Lucene42/Lucene42DocValuesProducer.cs
index e7e85dd..7a9df8a 100644
--- a/src/Lucene.Net/Codecs/Lucene42/Lucene42DocValuesProducer.cs
+++ b/src/Lucene.Net/Codecs/Lucene42/Lucene42DocValuesProducer.cs
@@ -1,5 +1,6 @@
 using J2N.Threading.Atomic;
 using Lucene.Net.Index;
+using Lucene.Net.Support.Threading;
 using Lucene.Net.Util.Fst;
 using System;
 using System.Collections.Generic;
@@ -222,7 +223,8 @@ namespace Lucene.Net.Codecs.Lucene42
 
         public override NumericDocValues GetNumeric(FieldInfo field)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (!numericInstances.TryGetValue(field.Number, out NumericDocValues instance) || instance == null)
                 {
@@ -231,6 +233,10 @@ namespace Lucene.Net.Codecs.Lucene42
                 }
                 return instance;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         public override long RamBytesUsed() => ramBytesUsed;
@@ -348,7 +354,8 @@ namespace Lucene.Net.Codecs.Lucene42
 
         public override BinaryDocValues GetBinary(FieldInfo field)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (!binaryInstances.TryGetValue(field.Number, out BinaryDocValues instance) || instance == null)
                 {
@@ -357,6 +364,10 @@ namespace Lucene.Net.Codecs.Lucene42
                 }
                 return instance;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         private BinaryDocValues LoadBinary(FieldInfo field)
@@ -422,7 +433,8 @@ namespace Lucene.Net.Codecs.Lucene42
         {
             FSTEntry entry = fsts[field.Number];
             FST<long?> instance;
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (!fstInstances.TryGetValue(field.Number, out instance) || instance == null)
                 {
@@ -432,6 +444,10 @@ namespace Lucene.Net.Codecs.Lucene42
                     fstInstances[field.Number] = instance;
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
             var docToOrd = GetNumeric(field);
             var fst = instance;
 
@@ -533,7 +549,8 @@ namespace Lucene.Net.Codecs.Lucene42
                 return DocValues.EMPTY_SORTED_SET; // empty FST!
             }
             FST<long?> instance;
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (!fstInstances.TryGetValue(field.Number, out instance) || instance == null)
                 {
@@ -543,6 +560,10 @@ namespace Lucene.Net.Codecs.Lucene42
                     fstInstances[field.Number] = instance;
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
             BinaryDocValues docToOrds = GetBinary(field);
             FST<long?> fst = instance;
 
diff --git a/src/Lucene.Net/Codecs/Lucene45/Lucene45DocValuesProducer.cs b/src/Lucene.Net/Codecs/Lucene45/Lucene45DocValuesProducer.cs
index f0f945d..36b9d6a 100644
--- a/src/Lucene.Net/Codecs/Lucene45/Lucene45DocValuesProducer.cs
+++ b/src/Lucene.Net/Codecs/Lucene45/Lucene45DocValuesProducer.cs
@@ -2,6 +2,7 @@
 using J2N.Threading.Atomic;
 using Lucene.Net.Diagnostics;
 using Lucene.Net.Index;
+using Lucene.Net.Support.Threading;
 using Lucene.Net.Util;
 using System;
 using System.Collections.Generic;
@@ -507,7 +508,8 @@ namespace Lucene.Net.Codecs.Lucene45
         protected virtual MonotonicBlockPackedReader GetAddressInstance(IndexInput data, FieldInfo field, BinaryEntry bytes)
         {
             MonotonicBlockPackedReader addresses;
-            lock (addressInstances)
+            UninterruptableMonitor.Enter(addressInstances);
+            try
             {
                 if (!addressInstances.TryGetValue(field.Number, out MonotonicBlockPackedReader addrInstance) || addrInstance == null)
                 {
@@ -518,6 +520,10 @@ namespace Lucene.Net.Codecs.Lucene45
                 }
                 addresses = addrInstance;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(addressInstances);
+            }
             return addresses;
         }
 
@@ -576,7 +582,8 @@ namespace Lucene.Net.Codecs.Lucene45
         {
             MonotonicBlockPackedReader addresses;
             long interval = bytes.AddressInterval;
-            lock (addressInstances)
+            UninterruptableMonitor.Enter(addressInstances);
+            try
             {
                 if (!addressInstances.TryGetValue(field.Number, out MonotonicBlockPackedReader addrInstance))
                 {
@@ -596,6 +603,10 @@ namespace Lucene.Net.Codecs.Lucene45
                 }
                 addresses = addrInstance;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(addressInstances);
+            }
             return addresses;
         }
 
@@ -683,7 +694,8 @@ namespace Lucene.Net.Codecs.Lucene45
         protected virtual MonotonicBlockPackedReader GetOrdIndexInstance(IndexInput data, FieldInfo field, NumericEntry entry)
         {
             MonotonicBlockPackedReader ordIndex;
-            lock (ordIndexInstances)
+            UninterruptableMonitor.Enter(ordIndexInstances);
+            try
             {
                 if (!ordIndexInstances.TryGetValue(field.Number, out MonotonicBlockPackedReader ordIndexInstance))
                 {
@@ -694,6 +706,10 @@ namespace Lucene.Net.Codecs.Lucene45
                 }
                 ordIndex = ordIndexInstance;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(ordIndexInstances);
+            }
             return ordIndex;
         }
 
diff --git a/src/Lucene.Net/Index/BufferedUpdatesStream.cs b/src/Lucene.Net/Index/BufferedUpdatesStream.cs
index 526586b..3139391 100644
--- a/src/Lucene.Net/Index/BufferedUpdatesStream.cs
+++ b/src/Lucene.Net/Index/BufferedUpdatesStream.cs
@@ -1,6 +1,7 @@
 using J2N.Text;
 using J2N.Threading.Atomic;
 using Lucene.Net.Diagnostics;
+using Lucene.Net.Support.Threading;
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
@@ -78,7 +79,8 @@ namespace Lucene.Net.Index
         /// </summary>
         public virtual long Push(FrozenBufferedUpdates packet)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 /*
                  * The insert operation must be atomic. If we let threads increment the gen
@@ -105,17 +107,26 @@ namespace Lucene.Net.Index
                 if (Debugging.AssertsEnabled) Debugging.Assert(CheckDeleteStats());
                 return packet.DelGen;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         public virtual void Clear()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 updates.Clear();
                 nextGen = 1;
                 numTerms.Value = 0;
                 bytesUsed.Value = 0;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         public virtual bool Any() => bytesUsed != 0;
@@ -169,7 +180,8 @@ namespace Lucene.Net.Index
         [MethodImpl(MethodImplOptions.NoInlining)]
         public virtual ApplyDeletesResult ApplyDeletesAndUpdates(IndexWriter.ReaderPool readerPool, IList<SegmentCommitInfo> infos)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 long t0 = J2N.Time.NanoTime() / J2N.Time.MillisecondsPerNanosecond; // LUCENENET: Use NanoTime() rather than CurrentTimeMilliseconds() for more accurate/reliable results
 
@@ -371,14 +383,23 @@ namespace Lucene.Net.Index
 
                 return new ApplyDeletesResult(anyNewDeletes, gen, allDeleted);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         internal virtual long GetNextGen()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 return nextGen++;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         // Lock order IW -> BD
@@ -390,7 +411,8 @@ namespace Lucene.Net.Index
         /// </summary>
         public virtual void Prune(SegmentInfos segmentInfos)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (Debugging.AssertsEnabled) Debugging.Assert(CheckDeleteStats());
                 long minGen = long.MaxValue;
@@ -422,11 +444,16 @@ namespace Lucene.Net.Index
                     Debugging.Assert(CheckDeleteStats());
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         private void Prune(int count)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (count > 0)
                 {
@@ -445,12 +472,17 @@ namespace Lucene.Net.Index
                     updates.RemoveRange(0, count); // LUCENENET: Checked count parameter for correctness
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         // Delete by Term
         private long ApplyTermDeletes(IEnumerable<Term> termsIter, ReadersAndUpdates rld, SegmentReader reader)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 long delCount = 0;
                 Fields fields = reader.Fields;
@@ -535,12 +567,17 @@ namespace Lucene.Net.Index
 
                 return delCount;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         // DocValues updates
         private void ApplyDocValuesUpdates<T1>(IEnumerable<T1> updates, ReadersAndUpdates rld, SegmentReader reader, DocValuesFieldUpdates.Container dvUpdatesContainer) where T1 : DocValuesUpdate
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 Fields fields = reader.Fields;
                 if (fields == null)
@@ -627,6 +664,10 @@ namespace Lucene.Net.Index
                     }
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         public class QueryAndLimit
diff --git a/src/Lucene.Net/Index/ConcurrentMergeScheduler.cs b/src/Lucene.Net/Index/ConcurrentMergeScheduler.cs
index 16c3b00..c653b42 100644
--- a/src/Lucene.Net/Index/ConcurrentMergeScheduler.cs
+++ b/src/Lucene.Net/Index/ConcurrentMergeScheduler.cs
@@ -1,5 +1,6 @@
 using J2N.Threading;
 using Lucene.Net.Diagnostics;
+using Lucene.Net.Support.Threading;
 using System;
 using System.Collections.Generic;
 using System.Runtime.CompilerServices;
@@ -149,11 +150,16 @@ namespace Lucene.Net.Index
         {
             get
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     InitMergeThreadPriority();
                     return mergeThreadPriority;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
@@ -167,7 +173,8 @@ namespace Lucene.Net.Index
         /// </summary>
         public virtual void SetMergeThreadPriority(int priority)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (priority > (int)ThreadPriority.Highest || priority < (int)ThreadPriority.Lowest)
                 {
@@ -176,6 +183,10 @@ namespace Lucene.Net.Index
                 mergeThreadPriority = priority;
                 UpdateMergeThreads();
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -199,7 +210,8 @@ namespace Lucene.Net.Index
         /// </summary>
         protected virtual void UpdateMergeThreads()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 // Only look at threads that are alive & not in the
                 // process of stopping (ie have an active merge):
@@ -269,6 +281,10 @@ namespace Lucene.Net.Index
                     }
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -295,7 +311,8 @@ namespace Lucene.Net.Index
 
         private void InitMergeThreadPriority()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (mergeThreadPriority == -1)
                 {
@@ -308,6 +325,10 @@ namespace Lucene.Net.Index
                     }
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         protected override void Dispose(bool disposing)
@@ -325,7 +346,8 @@ namespace Lucene.Net.Index
                 while (true)
                 {
                     MergeThread toSync = null;
-                    lock (this)
+                    UninterruptableMonitor.Enter(this);
+                    try
                     {
                         foreach (MergeThread t in m_mergeThreads)
                         {
@@ -336,6 +358,10 @@ namespace Lucene.Net.Index
                             }
                         }
                     }
+                    finally
+                    {
+                        UninterruptableMonitor.Exit(this);
+                    }
                     if (toSync != null)
                     {
                         try
@@ -372,7 +398,8 @@ namespace Lucene.Net.Index
         {
             get
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     int count = 0;
                     foreach (MergeThread mt in m_mergeThreads)
@@ -384,15 +411,20 @@ namespace Lucene.Net.Index
                     }
                     return count;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
         [MethodImpl(MethodImplOptions.NoInlining)]
         public override void Merge(IndexWriter writer, MergeTrigger trigger, bool newMergesFound)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
-                if (Debugging.AssertsEnabled) Debugging.Assert(!Monitor.IsEntered(writer));
+                if (Debugging.AssertsEnabled) Debugging.Assert(!UninterruptableMonitor.IsEntered(writer));
 
                 this.m_writer = writer;
 
@@ -436,7 +468,7 @@ namespace Lucene.Net.Index
                         }
                         try
                         {
-                            Monitor.Wait(this);
+                            UninterruptableMonitor.Wait(this);
                         }
                         catch (Exception ie) when (ie.IsInterruptedException())
                         {
@@ -497,6 +529,10 @@ namespace Lucene.Net.Index
                     }
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -511,7 +547,8 @@ namespace Lucene.Net.Index
         /// Create and return a new <see cref="MergeThread"/> </summary>
         protected virtual MergeThread GetMergeThread(IndexWriter writer, MergePolicy.OneMerge merge)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 MergeThread thread = new MergeThread(this, writer, merge);
                 thread.SetThreadPriority((ThreadPriority)mergeThreadPriority);
@@ -519,6 +556,10 @@ namespace Lucene.Net.Index
                 thread.Name = "Lucene Merge Thread #" + m_mergeThreadCount++;
                 return thread;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -549,17 +590,27 @@ namespace Lucene.Net.Index
             {
                 set
                 {
-                    lock (this)
+                    UninterruptableMonitor.Enter(this);
+                    try
                     {
                         runningMerge = value;
                     }
+                    finally
+                    {
+                        UninterruptableMonitor.Exit(this);
+                    }
                 }
                 get
                 {
-                    lock (this)
+                    UninterruptableMonitor.Enter(this);
+                    try
                     {
                         return runningMerge;
                     }
+                    finally
+                    {
+                        UninterruptableMonitor.Exit(this);
+                    }
                 }
             }
 
@@ -571,7 +622,8 @@ namespace Lucene.Net.Index
             {
                 get
                 {
-                    lock (this)
+                    UninterruptableMonitor.Enter(this);
+                    try
                     {
                         if (done)
                         {
@@ -586,6 +638,10 @@ namespace Lucene.Net.Index
                             return startMerge;
                         }
                     }
+                    finally
+                    {
+                        UninterruptableMonitor.Exit(this);
+                    }
                 }
             }
 
@@ -639,9 +695,14 @@ namespace Lucene.Net.Index
                         // Notify here in case any threads were stalled;
                         // they will notice that the pending merge has
                         // been pulled and possibly resume:
-                        lock (outerInstance)
+                        UninterruptableMonitor.Enter(outerInstance);
+                        try
                         {
-                            Monitor.PulseAll(outerInstance);
+                            UninterruptableMonitor.PulseAll(outerInstance);
+                        }
+                        finally
+                        {
+                            UninterruptableMonitor.Exit(outerInstance);
                         }
 
                         if (merge != null)
@@ -681,10 +742,15 @@ namespace Lucene.Net.Index
                 finally
                 {
                     done = true;
-                    lock (outerInstance)
+                    UninterruptableMonitor.Enter(outerInstance);
+                    try
                     {
                         outerInstance.UpdateMergeThreads();
-                        Monitor.PulseAll(outerInstance);
+                        UninterruptableMonitor.PulseAll(outerInstance);
+                    }
+                    finally
+                    {
+                        UninterruptableMonitor.Exit(outerInstance);
                     }
                 }
             }
diff --git a/src/Lucene.Net/Index/DocumentsWriter.cs b/src/Lucene.Net/Index/DocumentsWriter.cs
index 2bbde15..a1745bf 100644
--- a/src/Lucene.Net/Index/DocumentsWriter.cs
+++ b/src/Lucene.Net/Index/DocumentsWriter.cs
@@ -1,5 +1,6 @@
 using J2N.Threading.Atomic;
 using Lucene.Net.Diagnostics;
+using Lucene.Net.Support.Threading;
 using System;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
@@ -146,7 +147,8 @@ namespace Lucene.Net.Index
 
         internal bool DeleteQueries(params Query[] queries)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 // TODO why is this synchronized?
                 DocumentsWriterDeleteQueue deleteQueue = this.deleteQueue;
@@ -154,6 +156,10 @@ namespace Lucene.Net.Index
                 flushControl.DoOnDelete();
                 return ApplyAllDeletes(deleteQueue);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         // TODO: we could check w/ FreqProxTermsWriter: if the
@@ -161,7 +167,8 @@ namespace Lucene.Net.Index
         // per-DWPT map (but still must go into the global map)
         internal bool DeleteTerms(params Term[] terms)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 // TODO why is this synchronized?
                 DocumentsWriterDeleteQueue deleteQueue = this.deleteQueue;
@@ -169,28 +176,42 @@ namespace Lucene.Net.Index
                 flushControl.DoOnDelete();
                 return ApplyAllDeletes(deleteQueue);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         internal bool UpdateNumericDocValue(Term term, string field, long? value)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 DocumentsWriterDeleteQueue deleteQueue = this.deleteQueue;
                 deleteQueue.AddNumericUpdate(new NumericDocValuesUpdate(term, field, value));
                 flushControl.DoOnDelete();
                 return ApplyAllDeletes(deleteQueue);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         internal bool UpdateBinaryDocValue(Term term, string field, BytesRef value)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 DocumentsWriterDeleteQueue deleteQueue = this.deleteQueue;
                 deleteQueue.AddBinaryUpdate(new BinaryDocValuesUpdate(term, field, value));
                 flushControl.DoOnDelete();
                 return ApplyAllDeletes(deleteQueue);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         internal DocumentsWriterDeleteQueue CurrentDeleteSession => deleteQueue;
@@ -242,9 +263,10 @@ namespace Lucene.Net.Index
         [MethodImpl(MethodImplOptions.NoInlining)]
         internal void Abort(IndexWriter writer)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
-                if (Debugging.AssertsEnabled) Debugging.Assert(!Monitor.IsEntered(writer), "IndexWriter lock should never be hold when aborting");
+                if (Debugging.AssertsEnabled) Debugging.Assert(!UninterruptableMonitor.IsEntered(writer), "IndexWriter lock should never be hold when aborting");
                 bool success = false;
                 JCG.HashSet<string> newFilesSet = new JCG.HashSet<string>();
                 try
@@ -281,11 +303,16 @@ namespace Lucene.Net.Index
                     }
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         internal void LockAndAbortAll(IndexWriter indexWriter)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (Debugging.AssertsEnabled) Debugging.Assert(indexWriter.HoldsFullFlushLock);
                 if (infoStream.IsEnabled("DW"))
@@ -323,6 +350,10 @@ namespace Lucene.Net.Index
                     }
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         private void AbortThreadState(ThreadState perThread, ISet<string> newFiles)
@@ -356,7 +387,8 @@ namespace Lucene.Net.Index
 
         internal void UnlockAllAfterAbortAll(IndexWriter indexWriter)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (Debugging.AssertsEnabled) Debugging.Assert(indexWriter.HoldsFullFlushLock);
                 if (infoStream.IsEnabled("DW"))
@@ -384,6 +416,10 @@ namespace Lucene.Net.Index
                     }
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         internal bool AnyChanges()
@@ -708,11 +744,16 @@ namespace Lucene.Net.Index
         // for asserts
         private bool SetFlushingDeleteQueue(DocumentsWriterDeleteQueue session)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 currentFullFlushDelQueue = session;
                 return true;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /*
@@ -729,7 +770,8 @@ namespace Lucene.Net.Index
                 infoStream.Message("DW", "startFullFlush");
             }
 
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 pendingChangesInCurrentFullFlush = AnyChanges();
                 flushingDeleteQueue = deleteQueue;
@@ -739,6 +781,10 @@ namespace Lucene.Net.Index
                 flushControl.MarkForFullFlush(); // swaps the delQueue synced on FlushControl
                 if (Debugging.AssertsEnabled) Debugging.Assert(SetFlushingDeleteQueue(flushingDeleteQueue));
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
             if (Debugging.AssertsEnabled)
             {
                 Debugging.Assert(currentFullFlushDelQueue != null);
diff --git a/src/Lucene.Net/Index/DocumentsWriterFlushControl.cs b/src/Lucene.Net/Index/DocumentsWriterFlushControl.cs
index 124f8b7..f854ab0 100644
--- a/src/Lucene.Net/Index/DocumentsWriterFlushControl.cs
+++ b/src/Lucene.Net/Index/DocumentsWriterFlushControl.cs
@@ -1,6 +1,7 @@
 using J2N.Runtime.CompilerServices;
 using J2N.Threading.Atomic;
 using Lucene.Net.Diagnostics;
+using Lucene.Net.Support.Threading;
 using System;
 using System.Collections.Generic;
 using System.Threading;
@@ -86,10 +87,15 @@ namespace Lucene.Net.Index
         {
             get
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     return activeBytes;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
@@ -97,10 +103,15 @@ namespace Lucene.Net.Index
         {
             get
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     return flushBytes;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
@@ -108,10 +119,15 @@ namespace Lucene.Net.Index
         {
             get
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     return flushBytes + activeBytes;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
@@ -195,7 +211,8 @@ namespace Lucene.Net.Index
 
         internal DocumentsWriterPerThread DoAfterDocument(ThreadState perThread, bool isUpdate)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 try
                 {
@@ -242,6 +259,10 @@ namespace Lucene.Net.Index
                     if (Debugging.AssertsEnabled) Debugging.Assert(AssertNumDocsSinceStalled(stalled) && AssertMemory());
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         private bool AssertNumDocsSinceStalled(bool stalled)
@@ -266,7 +287,8 @@ namespace Lucene.Net.Index
 
         internal void DoAfterFlush(DocumentsWriterPerThread dwpt)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (Debugging.AssertsEnabled) Debugging.Assert(flushingWriters.ContainsKey(dwpt));
                 try
@@ -285,15 +307,19 @@ namespace Lucene.Net.Index
                     }
                     finally
                     {
-                        Monitor.PulseAll(this);
+                        UninterruptableMonitor.PulseAll(this);
                     }
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         private bool UpdateStallState()
         {
-            if (Debugging.AssertsEnabled) Debugging.Assert(Monitor.IsEntered(this));
+            if (Debugging.AssertsEnabled) Debugging.Assert(UninterruptableMonitor.IsEntered(this));
             long limit = StallLimitBytes;
             /*
              * we block indexing threads if net byte grows due to slow flushes
@@ -309,13 +335,14 @@ namespace Lucene.Net.Index
 
         public void WaitForFlush()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 while (flushingWriters.Count != 0)
                 {
                     try
                     {
-                        Monitor.Wait(this);
+                        UninterruptableMonitor.Wait(this);
                     }
                     catch (Exception ie) when (ie.IsInterruptedException())
                     {
@@ -323,6 +350,10 @@ namespace Lucene.Net.Index
                     }
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -332,7 +363,8 @@ namespace Lucene.Net.Index
         /// </summary>
         public void SetFlushPending(ThreadState perThread)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (Debugging.AssertsEnabled) Debugging.Assert(!perThread.flushPending);
                 if (perThread.dwpt.NumDocsInRAM > 0)
@@ -345,11 +377,16 @@ namespace Lucene.Net.Index
                     if (Debugging.AssertsEnabled) Debugging.Assert(AssertMemory());
                 } // don't assert on numDocs since we could hit an abort excp. while selecting that dwpt for flushing
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         internal void DoOnAbort(ThreadState state)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 try
                 {
@@ -370,15 +407,24 @@ namespace Lucene.Net.Index
                     UpdateStallState();
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         internal DocumentsWriterPerThread TryCheckoutForFlush(ThreadState perThread)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (Debugging.AssertsEnabled) Debugging.Assert(perThread.IsHeldByCurrentThread); // LUCENENET specific: Since .NET Core doesn't use unfair locking, we need to ensure the current thread has a lock before calling InternalTryCheckoutForFlush.
                 return perThread.flushPending ? InternalTryCheckOutForFlush(perThread) : null;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         private void CheckoutAndBlock(ThreadState perThread)
@@ -409,7 +455,7 @@ namespace Lucene.Net.Index
             {
                 // LUCENENET specific - Since we need to mimic the unfair behavior of ReentrantLock, we need to ensure that all threads that enter here hold the lock.
                 Debugging.Assert(perThread.IsHeldByCurrentThread);
-                Debugging.Assert(Monitor.IsEntered(this));
+                Debugging.Assert(UninterruptableMonitor.IsEntered(this));
                 Debugging.Assert(perThread.flushPending);
             }
             try
@@ -447,7 +493,8 @@ namespace Lucene.Net.Index
         {
             int numPending;
             bool fullFlush;
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 DocumentsWriterPerThread poll;
                 if (flushQueue.Count > 0 && (poll = flushQueue.Dequeue()) != null)
@@ -458,6 +505,10 @@ namespace Lucene.Net.Index
                 fullFlush = this.fullFlush;
                 numPending = this.numPending;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
             if (numPending > 0 && !fullFlush) // don't check if we are doing a full flush
             {
                 int limit = perThreadPool.NumThreadStatesActive;
@@ -486,7 +537,8 @@ namespace Lucene.Net.Index
 
         internal void SetClosed()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 // set by DW to signal that we should not release new DWPT after close
                 if (!closed)
@@ -495,6 +547,10 @@ namespace Lucene.Net.Index
                     perThreadPool.DeactivateUnreleasedStates();
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -551,11 +607,16 @@ namespace Lucene.Net.Index
 
         internal void DoOnDelete()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 // pass null this is a global delete no update
                 flushPolicy.OnDelete(this, null);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -569,10 +630,15 @@ namespace Lucene.Net.Index
         {
             get
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     return flushingWriters.Count;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
@@ -617,7 +683,8 @@ namespace Lucene.Net.Index
         internal void MarkForFullFlush()
         {
             DocumentsWriterDeleteQueue flushingQueue;
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (Debugging.AssertsEnabled)
                 {
@@ -631,6 +698,10 @@ namespace Lucene.Net.Index
                 DocumentsWriterDeleteQueue newQueue = new DocumentsWriterDeleteQueue(flushingQueue.generation + 1);
                 documentsWriter.deleteQueue = newQueue;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
             int limit = perThreadPool.NumThreadStatesActive;
             for (int i = 0; i < limit; i++)
             {
@@ -662,7 +733,8 @@ namespace Lucene.Net.Index
                     next.Unlock();
                 }
             }
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 /* make sure we move all DWPT that are where concurrently marked as
                  * pending and moved to blocked are moved over to the flushQueue. There is
@@ -678,6 +750,10 @@ namespace Lucene.Net.Index
                 fullFlushBuffer.Clear();
                 UpdateStallState();
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
             if (Debugging.AssertsEnabled) Debugging.Assert(AssertActiveDeleteQueue(documentsWriter.deleteQueue));
         }
 
@@ -718,7 +794,8 @@ namespace Lucene.Net.Index
             }
             if (dwpt.NumDocsInRAM > 0)
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     if (!perThread.flushPending)
                     {
@@ -732,6 +809,10 @@ namespace Lucene.Net.Index
                     }
                     fullFlushBuffer.Add(flushingDWPT);
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
             else
             {
@@ -764,7 +845,8 @@ namespace Lucene.Net.Index
 
         internal void FinishFullFlush()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (Debugging.AssertsEnabled)
                 {
@@ -787,6 +869,10 @@ namespace Lucene.Net.Index
                     UpdateStallState();
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         internal bool AssertBlockedFlushes(DocumentsWriterDeleteQueue flushingQueue)
@@ -800,7 +886,8 @@ namespace Lucene.Net.Index
 
         internal void AbortFullFlushes(ISet<string> newFiles)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 try
                 {
@@ -811,11 +898,16 @@ namespace Lucene.Net.Index
                     fullFlush = false;
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         internal void AbortPendingFlushes(ISet<string> newFiles)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 try
                 {
@@ -860,6 +952,10 @@ namespace Lucene.Net.Index
                     UpdateStallState();
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -869,10 +965,15 @@ namespace Lucene.Net.Index
         {
             get
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     return fullFlush;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
@@ -884,10 +985,15 @@ namespace Lucene.Net.Index
         {
             get
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     return flushQueue.Count;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
@@ -900,10 +1006,15 @@ namespace Lucene.Net.Index
         {
             get
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     return blockedFlushes.Count;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
diff --git a/src/Lucene.Net/Index/DocumentsWriterFlushQueue.cs b/src/Lucene.Net/Index/DocumentsWriterFlushQueue.cs
index 1c5dd96..6fafb00 100644
--- a/src/Lucene.Net/Index/DocumentsWriterFlushQueue.cs
+++ b/src/Lucene.Net/Index/DocumentsWriterFlushQueue.cs
@@ -1,4 +1,4 @@
-using J2N.Threading.Atomic;
+using J2N.Threading.Atomic;
 using Lucene.Net.Diagnostics;
 using Lucene.Net.Support.Threading;
 using System.Collections.Generic;
@@ -40,7 +40,8 @@ namespace Lucene.Net.Index
 
         internal virtual void AddDeletes(DocumentsWriterDeleteQueue deleteQueue)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 IncTickets(); // first inc the ticket count - freeze opens
                 // a window for #anyChanges to fail
@@ -58,6 +59,10 @@ namespace Lucene.Net.Index
                     }
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         private void IncTickets()
@@ -74,7 +79,8 @@ namespace Lucene.Net.Index
 
         internal virtual SegmentFlushTicket AddFlushTicket(DocumentsWriterPerThread dwpt)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 // Each flush is assigned a ticket in the order they acquire the ticketQueue
                 // lock
@@ -96,25 +102,39 @@ namespace Lucene.Net.Index
                     }
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         internal virtual void AddSegment(SegmentFlushTicket ticket, FlushedSegment segment)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 // the actual flush is done asynchronously and once done the FlushedSegment
                 // is passed to the flush ticket
                 ticket.SetSegment(segment);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         internal virtual void MarkTicketFailed(SegmentFlushTicket ticket)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 // to free the queue we mark tickets as failed just to clean up the queue.
                 ticket.SetFailed();
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         internal virtual bool HasTickets
@@ -134,11 +154,16 @@ namespace Lucene.Net.Index
             {
                 FlushTicket head;
                 bool canPublish;
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     head = queue.Count <= 0 ? null : queue.Peek();
                     canPublish = head != null && head.CanPublish; // do this synced
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
                 if (canPublish)
                 {
                     numPurged++;
@@ -154,13 +179,18 @@ namespace Lucene.Net.Index
                     }
                     finally
                     {
-                        lock (this)
+                        UninterruptableMonitor.Enter(this);
+                        try
                         {
                             // finally remove the published ticket from the queue
                             FlushTicket poll = queue.Dequeue();
                             ticketCount.DecrementAndGet();
                             if (Debugging.AssertsEnabled) Debugging.Assert(poll == head);
                         }
+                        finally
+                        {
+                            UninterruptableMonitor.Exit(this);
+                        }
                     }
                 }
                 else
@@ -175,8 +205,8 @@ namespace Lucene.Net.Index
         {
             if (Debugging.AssertsEnabled)
             {
-                Debugging.Assert(!Monitor.IsEntered(this));
-                Debugging.Assert(!Monitor.IsEntered(writer));
+                Debugging.Assert(!UninterruptableMonitor.IsEntered(this));
+                Debugging.Assert(!UninterruptableMonitor.IsEntered(writer));
             }
             purgeLock.@Lock();
             try
@@ -193,8 +223,8 @@ namespace Lucene.Net.Index
         {
             if (Debugging.AssertsEnabled)
             {
-                Debugging.Assert(!Monitor.IsEntered(this));
-                Debugging.Assert(!Monitor.IsEntered(writer));
+                Debugging.Assert(!UninterruptableMonitor.IsEntered(this));
+                Debugging.Assert(!UninterruptableMonitor.IsEntered(writer));
             }
             if (purgeLock.TryLock())
             {
@@ -214,11 +244,16 @@ namespace Lucene.Net.Index
 
         internal virtual void Clear()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 queue.Clear();
                 ticketCount.Value = 0;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         internal abstract class FlushTicket
diff --git a/src/Lucene.Net/Index/DocumentsWriterPerThreadPool.cs b/src/Lucene.Net/Index/DocumentsWriterPerThreadPool.cs
index 349af3c..1e5af16 100644
--- a/src/Lucene.Net/Index/DocumentsWriterPerThreadPool.cs
+++ b/src/Lucene.Net/Index/DocumentsWriterPerThreadPool.cs
@@ -239,7 +239,8 @@ namespace Lucene.Net.Index
 
         private bool AssertUnreleasedThreadStatesInactive()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 for (int i = numThreadStatesActive; i < threadStates.Length; i++)
                 {
@@ -255,6 +256,10 @@ namespace Lucene.Net.Index
                 }
                 return true;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -262,7 +267,8 @@ namespace Lucene.Net.Index
         /// </summary>
         internal void DeactivateUnreleasedStates()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 for (int i = numThreadStatesActive; i < threadStates.Length; i++)
                 {
@@ -278,6 +284,10 @@ namespace Lucene.Net.Index
                     }
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         internal static DocumentsWriterPerThread Reset(ThreadState threadState, bool closed) // LUCENENET: CA1822: Mark members as static
@@ -306,7 +316,8 @@ namespace Lucene.Net.Index
         public ThreadState GetAndLock(/* Thread requestingThread, DocumentsWriter documentsWriter // LUCENENET: Not referenced */)
         {
             ThreadState threadState = null;
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 for (;;)
                 {
@@ -352,7 +363,7 @@ namespace Lucene.Net.Index
                         // Wait until a thread state frees up:
                         try
                         {
-                            Monitor.Wait(this);
+                            UninterruptableMonitor.Wait(this);
                         }
                         catch (Exception ie) when (ie.IsInterruptedException())
                         {
@@ -361,6 +372,10 @@ namespace Lucene.Net.Index
                     }
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
 
             // This could take time, e.g. if the threadState is [briefly] checked for flushing:
             threadState.Lock();
@@ -371,13 +386,18 @@ namespace Lucene.Net.Index
         public void Release(ThreadState state)
         {
             state.Unlock();
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 Debug.Assert(freeCount < freeList.Length);
                 freeList[freeCount++] = state;
                 // In case any thread is waiting, wake one of them up since we just released a thread state; notify() should be sufficient but we do
                 // notifyAll defensively:
-                Monitor.PulseAll(this);
+                UninterruptableMonitor.PulseAll(this);
+            }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
             }
         }
 
diff --git a/src/Lucene.Net/Index/DocumentsWriterStallControl.cs b/src/Lucene.Net/Index/DocumentsWriterStallControl.cs
index fad1ab4..3f24887 100644
--- a/src/Lucene.Net/Index/DocumentsWriterStallControl.cs
+++ b/src/Lucene.Net/Index/DocumentsWriterStallControl.cs
@@ -1,6 +1,7 @@
 using J2N.Runtime.CompilerServices;
 using J2N.Threading;
 using Lucene.Net.Diagnostics;
+using Lucene.Net.Support.Threading;
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
@@ -58,14 +59,19 @@ namespace Lucene.Net.Index
         /// </summary>
         internal void UpdateStalled(bool stalled)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 this.stalled = stalled;
                 if (stalled)
                 {
                     wasStalled = true;
                 }
-                Monitor.PulseAll(this);
+                UninterruptableMonitor.PulseAll(this);
+            }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
             }
         }
 
@@ -77,7 +83,8 @@ namespace Lucene.Net.Index
         {
             if (stalled)
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     if (stalled) // react on the first wakeup call!
                     {
@@ -88,7 +95,7 @@ namespace Lucene.Net.Index
                             // disabled in production
                             var result = IncWaiters();
                             if (Debugging.AssertsEnabled) Debugging.Assert(result);
-                            Monitor.Wait(this);
+                            UninterruptableMonitor.Wait(this);
                             result = DecrWaiters();
                             if (Debugging.AssertsEnabled) Debugging.Assert(result);
                         }
@@ -98,6 +105,10 @@ namespace Lucene.Net.Index
                         }
                     }
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
@@ -128,10 +139,15 @@ namespace Lucene.Net.Index
         {
             get
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     return numWaiting > 0;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
@@ -139,20 +155,30 @@ namespace Lucene.Net.Index
 
         internal bool IsThreadQueued(ThreadJob t) // for tests
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 return waiting.ContainsKey(t);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         internal bool WasStalled // for tests
         {
             get
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     return wasStalled;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
     }
diff --git a/src/Lucene.Net/Index/FieldInfos.cs b/src/Lucene.Net/Index/FieldInfos.cs
index 9283d06..d8d05bd 100644
--- a/src/Lucene.Net/Index/FieldInfos.cs
+++ b/src/Lucene.Net/Index/FieldInfos.cs
@@ -1,5 +1,6 @@
 using J2N.Collections.Generic.Extensions;
 using Lucene.Net.Diagnostics;
+using Lucene.Net.Support.Threading;
 using System;
 using System.Collections;
 using System.Collections.Generic;
@@ -211,7 +212,8 @@ namespace Lucene.Net.Index
             /// </summary>
             internal int AddOrGet(string fieldName, int preferredFieldNumber, DocValuesType dvType)
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     if (dvType != DocValuesType.NONE)
                     {
@@ -249,12 +251,17 @@ namespace Lucene.Net.Index
 
                     return (int)fieldNumber;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
 
             // used by assert
             internal bool ContainsConsistent(int? number, string name, DocValuesType dvType)
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     numberToName.TryGetValue(number, out string numberToNameStr);
                     nameToNumber.TryGetValue(name, out int? nameToNumberVal);
@@ -264,6 +271,10 @@ namespace Lucene.Net.Index
                         && number.Equals(nameToNumber[name]) && 
                         (dvType == DocValuesType.NONE || docValuesType == DocValuesType.NONE || dvType == docValuesType);
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
 
             /// <summary>
@@ -272,7 +283,8 @@ namespace Lucene.Net.Index
             /// </summary>
             internal bool Contains(string fieldName, DocValuesType dvType)
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     // used by IndexWriter.updateNumericDocValue
                     if (!nameToNumber.ContainsKey(fieldName))
@@ -286,25 +298,39 @@ namespace Lucene.Net.Index
                         return dvType == dvCand;
                     }
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
 
             internal void Clear()
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     numberToName.Clear();
                     nameToNumber.Clear();
                     docValuesType.Clear();
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
 
             internal void SetDocValuesType(int number, string name, DocValuesType dvType)
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     if (Debugging.AssertsEnabled) Debugging.Assert(ContainsConsistent(number, name, dvType));
                     docValuesType[name] = dvType;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
diff --git a/src/Lucene.Net/Index/FlushPolicy.cs b/src/Lucene.Net/Index/FlushPolicy.cs
index b8c157a..51280b0 100644
--- a/src/Lucene.Net/Index/FlushPolicy.cs
+++ b/src/Lucene.Net/Index/FlushPolicy.cs
@@ -1,4 +1,5 @@
 using Lucene.Net.Diagnostics;
+using Lucene.Net.Support.Threading;
 using System.Collections.Generic;
 
 namespace Lucene.Net.Index
@@ -95,11 +96,16 @@ namespace Lucene.Net.Index
         /// </summary>
         protected internal virtual void Init(LiveIndexWriterConfig indexWriterConfig)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 this.m_indexWriterConfig = indexWriterConfig;
                 m_infoStream = indexWriterConfig.InfoStream;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
diff --git a/src/Lucene.Net/Index/IndexFileDeleter.cs b/src/Lucene.Net/Index/IndexFileDeleter.cs
index 107c250..fa7cd3f 100644
--- a/src/Lucene.Net/Index/IndexFileDeleter.cs
+++ b/src/Lucene.Net/Index/IndexFileDeleter.cs
@@ -1,5 +1,6 @@
 using Lucene.Net.Diagnostics;
 using Lucene.Net.Support;
+using Lucene.Net.Support.Threading;
 using System;
 using System.Collections.Generic;
 using System.IO;
@@ -118,7 +119,7 @@ namespace Lucene.Net.Index
 
         // called only from assert
         private bool IsLocked =>
-            writer == null || Monitor.IsEntered(writer);
+            writer == null || UninterruptableMonitor.IsEntered(writer);
 
         /// <summary>
         /// Initialize the deleter: find all previous commits in
@@ -496,7 +497,7 @@ namespace Lucene.Net.Index
             {
                 Debugging.Assert(IsLocked);
 
-                Debugging.Assert(Monitor.IsEntered(writer));
+                Debugging.Assert(UninterruptableMonitor.IsEntered(writer));
             }
             long t0 = 0;
             if (infoStream.IsEnabled("IFD"))
diff --git a/src/Lucene.Net/Index/IndexReader.cs b/src/Lucene.Net/Index/IndexReader.cs
index c75c80b..2e30b45 100644
--- a/src/Lucene.Net/Index/IndexReader.cs
+++ b/src/Lucene.Net/Index/IndexReader.cs
@@ -1,6 +1,7 @@
 using J2N.Threading.Atomic;
 using Lucene.Net.Documents;
 using Lucene.Net.Support;
+using Lucene.Net.Support.Threading;
 using Lucene.Net.Util;
 using System;
 using System.Collections;
@@ -145,17 +146,26 @@ namespace Lucene.Net.Index
             EnsureOpen();
             // LUCENENET specific - since neither WeakDictionary nor ConditionalWeakTable synchronize
             // on the enumerator, we need to do external synchronization to make them threadsafe.
-            lock (parentReadersLock)
+            UninterruptableMonitor.Enter(parentReadersLock);
+            try
+            {
                 // LUCENENET: Since there is a set Add operation (unique) in Lucene, the equivalent
                 // operation in .NET is AddOrUpdate, which effectively does nothing if the key exists.
                 // Null is passed as a value, since it is not used anyway and .NET doesn't have a boolean
                 // reference type.
                 parentReaders.AddOrUpdate(key: reader, value: null);
+            }
+            finally
+            {
+                UninterruptableMonitor.Exit(parentReadersLock);
+            }
         }
 
         private void NotifyReaderClosedListeners(Exception th)
         {
-            lock (((ICollection)readerClosedListeners).SyncRoot) // LUCENENET: Ensure we sync on the SyncRoot of ConcurrentSet<T>
+            object syncRoot = ((ICollection)readerClosedListeners).SyncRoot;
+            UninterruptableMonitor.Enter(syncRoot); // LUCENENET: Ensure we sync on the SyncRoot of ConcurrentSet<T>
+            try
             {
                 foreach (IReaderClosedListener listener in readerClosedListeners)
                 {
@@ -177,13 +187,18 @@ namespace Lucene.Net.Index
                 }
                 IOUtils.ReThrowUnchecked(th);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(syncRoot);
+            }
         }
 
         private void ReportCloseToParentReaders()
         {
             // LUCENENET specific - since neither WeakDictionary nor ConditionalWeakTable synchronize
             // on the enumerator, we need to do external synchronization to make them threadsafe.
-            lock (parentReadersLock)
+            UninterruptableMonitor.Enter(parentReadersLock);
+            try
             {
                 foreach (var kvp in parentReaders)
                 {
@@ -201,6 +216,10 @@ namespace Lucene.Net.Index
                     }
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(parentReadersLock);
+            }
         }
 
         /// <summary>
@@ -568,7 +587,8 @@ namespace Lucene.Net.Index
         {
             if (disposing)
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     if (!closed)
                     {
@@ -576,6 +596,10 @@ namespace Lucene.Net.Index
                         closed = true;
                     }
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
diff --git a/src/Lucene.Net/Index/IndexWriter.cs b/src/Lucene.Net/Index/IndexWriter.cs
index adda7ea..6e320fe 100644
--- a/src/Lucene.Net/Index/IndexWriter.cs
+++ b/src/Lucene.Net/Index/IndexWriter.cs
@@ -4,6 +4,7 @@ using J2N.Threading;
 using J2N.Threading.Atomic;
 using Lucene.Net.Diagnostics;
 using Lucene.Net.Support;
+using Lucene.Net.Support.Threading;
 using System;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
@@ -372,7 +373,8 @@ namespace Lucene.Net.Index
             bool success2 = false;
             try
             {
-                lock (fullFlushLock)
+                UninterruptableMonitor.Enter(fullFlushLock);
+                try
                 {
                     bool success = false;
                     try
@@ -388,7 +390,8 @@ namespace Lucene.Net.Index
                         // Prevent segmentInfos from changing while opening the
                         // reader; in theory we could instead do similar retry logic,
                         // just like we do when loading segments_N
-                        lock (this)
+                        UninterruptableMonitor.Enter(this);
+                        try
                         {
                             MaybeApplyDeletes(applyAllDeletes);
                             r = StandardDirectoryReader.Open(this, segmentInfos, applyAllDeletes);
@@ -397,6 +400,10 @@ namespace Lucene.Net.Index
                                 infoStream.Message("IW", "return reader version=" + r.Version + " reader=" + r);
                             }
                         }
+                        finally
+                        {
+                            UninterruptableMonitor.Exit(this);
+                        }
                     }
                     catch (Exception oom) when (oom.IsOutOfMemoryError())
                     {
@@ -419,6 +426,10 @@ namespace Lucene.Net.Index
                         DoAfterFlush();
                     }
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(fullFlushLock);
+                }
                 if (anySegmentFlushed)
                 {
                     MaybeMerge(MergeTrigger.FULL_FLUSH, UNBOUNDED_MAX_MERGE_SEGMENTS);
@@ -467,18 +478,24 @@ namespace Lucene.Net.Index
             // used only by asserts
             public virtual bool InfoIsLive(SegmentCommitInfo info)
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     int idx = outerInstance.segmentInfos.IndexOf(info);
                     Debugging.Assert(idx != -1, "info={0} isn't live", info);
                     Debugging.Assert(outerInstance.segmentInfos.Info(idx) == info, "info={0} doesn't match live info in segmentInfos", info);
                     return true;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
 
             public virtual void Drop(SegmentCommitInfo info)
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     if (readerMap.TryGetValue(info, out ReadersAndUpdates rld) && rld != null)
                     {
@@ -488,11 +505,16 @@ namespace Lucene.Net.Index
                         rld.DropReaders();
                     }
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
 
             public virtual bool AnyPendingDeletes()
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     foreach (ReadersAndUpdates rld in readerMap.Values)
                     {
@@ -504,19 +526,29 @@ namespace Lucene.Net.Index
 
                     return false;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
 
             public virtual void Release(ReadersAndUpdates rld)
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     Release(rld, true);
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
 
             public virtual void Release(ReadersAndUpdates rld, bool assertInfoLive)
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     // Matches incRef in get:
                     rld.DecRef();
@@ -549,6 +581,10 @@ namespace Lucene.Net.Index
                         readerMap.Remove(rld.Info);
                     }
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
 
             public void Dispose()
@@ -562,7 +598,8 @@ namespace Lucene.Net.Index
             /// </summary>
             internal virtual void DropAll(bool doSave)
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     Exception priorE = null;
                     foreach (var pair in readerMap)
@@ -628,6 +665,10 @@ namespace Lucene.Net.Index
                     if (Debugging.AssertsEnabled) Debugging.Assert(readerMap.Count == 0);
                     IOUtils.ReThrow(priorE);
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
 
             /// <summary>
@@ -637,7 +678,8 @@ namespace Lucene.Net.Index
             /// <exception cref="IOException"> If there is a low-level I/O error </exception>
             public virtual void Commit(SegmentInfos infos)
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     foreach (SegmentCommitInfo info in infos.Segments)
                     {
@@ -660,6 +702,10 @@ namespace Lucene.Net.Index
                         }
                     }
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
 
             /// <summary>
@@ -669,7 +715,8 @@ namespace Lucene.Net.Index
             /// </summary>
             public virtual ReadersAndUpdates Get(SegmentCommitInfo info, bool create)
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     if (Debugging.AssertsEnabled) Debugging.Assert(info.Info.Dir == outerInstance.directory, "info.dir={0} vs {1}", info.Info.Dir, outerInstance.directory);
 
@@ -699,6 +746,10 @@ namespace Lucene.Net.Index
 
                     return rld;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
 
             /// <summary>
@@ -896,10 +947,15 @@ namespace Lucene.Net.Index
 
                 // Default deleter (for backwards compatibility) is
                 // KeepOnlyLastCommitDeleter:
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     deleter = new IndexFileDeleter(directory, config.IndexDeletionPolicy, segmentInfos, infoStream, this, initialIndexExists);
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
 
                 if (deleter.startingCommitDeleted)
                 {
@@ -1060,7 +1116,8 @@ namespace Lucene.Net.Index
         {
             // Ensure that only one thread actually gets to do the
             // closing, and make sure no commit is also in progress:
-            lock (commitLock)
+            UninterruptableMonitor.Enter(commitLock);
+            try
             {
                 if (ShouldClose())
                 {
@@ -1078,6 +1135,10 @@ namespace Lucene.Net.Index
                     }
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(commitLock);
+            }
         }
 
         private bool AssertEventQueueAfterClose()
@@ -1100,7 +1161,8 @@ namespace Lucene.Net.Index
         /// </summary>
         private bool ShouldClose()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 while (true)
                 {
@@ -1125,6 +1187,10 @@ namespace Lucene.Net.Index
                     }
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         private void CloseInternal(bool waitForMerges, bool doFlush)
@@ -1189,7 +1255,8 @@ namespace Lucene.Net.Index
                             }
                         }
 
-                        lock (this)
+                        UninterruptableMonitor.Enter(this);
+                        try
                         {
                             for (; ; )
                             {
@@ -1212,6 +1279,10 @@ namespace Lucene.Net.Index
                             }
                             stopMerges = true;
                         }
+                        finally
+                        {
+                            UninterruptableMonitor.Exit(this);
+                        }
                     }
                     finally
                     {
@@ -1230,7 +1301,8 @@ namespace Lucene.Net.Index
                     CommitInternal();
                 }
                 ProcessEvents(false, true);
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     // commitInternal calls ReaderPool.commit, which
                     // writes any pending liveDocs from ReaderPool, so
@@ -1238,6 +1310,10 @@ namespace Lucene.Net.Index
                     readerPool.DropAll(true);
                     deleter.Dispose();
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
 
                 if (infoStream.IsEnabled("IW"))
                 {
@@ -1249,10 +1325,15 @@ namespace Lucene.Net.Index
                     writeLock.Dispose(); // release write lock
                     writeLock = null;
                 }
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     closed = true;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
                 if (Debugging.AssertsEnabled)
                 {
                     // LUCENENET specific - store the number of states so we don't have to call this method twice
@@ -1266,10 +1347,11 @@ namespace Lucene.Net.Index
             }
             finally
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     closing = false;
-                    Monitor.PulseAll(this);
+                    UninterruptableMonitor.PulseAll(this);
                     if (!closed)
                     {
                         if (infoStream.IsEnabled("IW"))
@@ -1278,6 +1360,10 @@ namespace Lucene.Net.Index
                         }
                     }
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
                 // finally, restore interrupt status:
                 if (interrupted)
                 {
@@ -1311,11 +1397,16 @@ namespace Lucene.Net.Index
         {
             get
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     EnsureOpen();
                     return docWriter.NumDocs + segmentInfos.TotalDocCount;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
@@ -1331,7 +1422,8 @@ namespace Lucene.Net.Index
         {
             get
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     EnsureOpen();
                     int count = docWriter.NumDocs;
@@ -1341,6 +1433,10 @@ namespace Lucene.Net.Index
                     }
                     return count;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
@@ -1353,7 +1449,8 @@ namespace Lucene.Net.Index
         /// </summary>
         public virtual bool HasDeletions()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 EnsureOpen();
                 if (bufferedUpdatesStream.Any())
@@ -1377,6 +1474,10 @@ namespace Lucene.Net.Index
                 }
                 return false;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -1607,7 +1708,8 @@ namespace Lucene.Net.Index
         /// </summary>
         public virtual bool TryDeleteDocument(IndexReader readerIn, int docID)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (!(readerIn is AtomicReader reader))
                 {
@@ -1641,7 +1743,8 @@ namespace Lucene.Net.Index
                     ReadersAndUpdates rld = readerPool.Get(info, false);
                     if (rld != null)
                     {
-                        lock (bufferedUpdatesStream)
+                        UninterruptableMonitor.Enter(bufferedUpdatesStream);
+                        try
                         {
                             rld.InitWritableLiveDocs();
                             if (rld.Delete(docID))
@@ -1668,6 +1771,10 @@ namespace Lucene.Net.Index
                             //System.out.println("  yes " + info.info.name + " " + docID);
                             return true;
                         }
+                        finally
+                        {
+                            UninterruptableMonitor.Exit(bufferedUpdatesStream);
+                        }
                     }
                     else
                     {
@@ -1680,6 +1787,10 @@ namespace Lucene.Net.Index
                 }
                 return false;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -1928,10 +2039,15 @@ namespace Lucene.Net.Index
         {
             get
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     return segmentInfos.Count;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
@@ -1940,10 +2056,15 @@ namespace Lucene.Net.Index
         {
             get
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     return docWriter.NumDocs;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
@@ -1952,17 +2073,23 @@ namespace Lucene.Net.Index
         {
             get
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     return segmentInfos.GetFiles(directory, true);
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
         // for test purpose
         internal int GetDocCount(int i)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (i >= 0 && i < segmentInfos.Count)
                 {
@@ -1973,6 +2100,10 @@ namespace Lucene.Net.Index
                     return -1;
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         // for test purpose
@@ -1985,7 +2116,8 @@ namespace Lucene.Net.Index
         {
             // Cannot synchronize on IndexWriter because that causes
             // deadlock
-            lock (segmentInfos)
+            UninterruptableMonitor.Enter(segmentInfos);
+            try
             {
                 // Important to increment changeCount so that the
                 // segmentInfos is written on close.  Otherwise we
@@ -1996,6 +2128,10 @@ namespace Lucene.Net.Index
                 segmentInfos.Changed();
                 return "_" + (segmentInfos.Counter++).ToString(J2N.Character.MaxRadix);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(segmentInfos);
+            }
         }
 
         /// <summary>
@@ -2099,7 +2235,8 @@ namespace Lucene.Net.Index
 
             Flush(true, true);
 
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 ResetMergeExceptions();
                 segmentsToMerge.Clear();
@@ -2123,12 +2260,17 @@ namespace Lucene.Net.Index
                     if (merge.Info != null) segmentsToMerge[merge.Info] = true;
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
 
             MaybeMerge(MergeTrigger.EXPLICIT, maxNumSegments);
 
             if (doWait)
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     while (true)
                     {
@@ -2170,6 +2312,10 @@ namespace Lucene.Net.Index
                         }
                     }
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
 
                 // If close is called while we are still
                 // running, throw an exception so the calling
@@ -2177,6 +2323,7 @@ namespace Lucene.Net.Index
                 // complete
                 EnsureOpen();
             }
+
             // NOTE: in the ConcurrentMergeScheduler case, when
             // doWait is false, we can return immediately while
             // background threads accomplish the merging
@@ -2188,7 +2335,8 @@ namespace Lucene.Net.Index
         /// </summary>
         private bool MaxNumSegmentsMergesPending()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 foreach (MergePolicy.OneMerge merge in pendingMerges)
                 {
@@ -2208,6 +2356,10 @@ namespace Lucene.Net.Index
 
                 return false;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -2239,7 +2391,9 @@ namespace Lucene.Net.Index
 
             MergePolicy.MergeSpecification spec;
             bool newMergesFound = false;
-            lock (this)
+
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 spec = mergePolicy.FindForcedDeletesMerges(segmentInfos);
                 newMergesFound = spec != null;
@@ -2252,13 +2406,18 @@ namespace Lucene.Net.Index
                     }
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
 
             mergeScheduler.Merge(this, MergeTrigger.EXPLICIT, newMergesFound);
 
             if (spec != null && doWait)
             {
                 int numMerges = spec.Merges.Count;
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     bool running = true;
                     while (running)
@@ -2293,6 +2452,10 @@ namespace Lucene.Net.Index
                         }
                     }
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
 
             // NOTE: in the ConcurrentMergeScheduler case, when
@@ -2359,7 +2522,8 @@ namespace Lucene.Net.Index
 
         private bool UpdatePendingMerges(MergeTrigger trigger, int maxNumSegments)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (Debugging.AssertsEnabled) Debugging.Assert(maxNumSegments == -1 || maxNumSegments > 0);
                 //if (Debugging.AssertsEnabled) Debugging.Assert(trigger != null); // LUCENENET NOTE: Enum cannot be null in .NET
@@ -2377,7 +2541,7 @@ namespace Lucene.Net.Index
                 MergePolicy.MergeSpecification spec;
                 if (maxNumSegments != UNBOUNDED_MAX_MERGE_SEGMENTS)
                 {
-                    if (Debugging.AssertsEnabled) Debugging.Assert(trigger == MergeTrigger.EXPLICIT || trigger == MergeTrigger.MERGE_FINISHED,"Expected EXPLICT or MERGE_FINISHED as trigger even with maxNumSegments set but was: {0}", trigger);
+                    if (Debugging.AssertsEnabled) Debugging.Assert(trigger == MergeTrigger.EXPLICIT || trigger == MergeTrigger.MERGE_FINISHED, "Expected EXPLICT or MERGE_FINISHED as trigger even with maxNumSegments set but was: {0}", trigger);
                     spec = mergePolicy.FindForcedMerges(segmentInfos, maxNumSegments, segmentsToMerge);
                     newMergesFound = spec != null;
                     if (newMergesFound)
@@ -2405,6 +2569,10 @@ namespace Lucene.Net.Index
                 }
                 return newMergesFound;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -2421,10 +2589,15 @@ namespace Lucene.Net.Index
         {
             get
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     return mergingSegments;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
@@ -2436,7 +2609,8 @@ namespace Lucene.Net.Index
         /// </summary>
         public virtual MergePolicy.OneMerge NextMerge()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (pendingMerges.Count == 0)
                 {
@@ -2450,6 +2624,10 @@ namespace Lucene.Net.Index
                     return merge;
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -2459,10 +2637,15 @@ namespace Lucene.Net.Index
         /// </summary>
         public virtual bool HasPendingMerges()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 return pendingMerges.Count != 0;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -2482,13 +2665,18 @@ namespace Lucene.Net.Index
 
             // Ensure that only one thread actually gets to do the
             // closing, and make sure no commit is also in progress:
-            lock (commitLock)
+            UninterruptableMonitor.Enter(commitLock);
+            try
             {
                 if (ShouldClose())
                 {
                     RollbackInternal();
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(commitLock);
+            }
         }
 
         [MethodImpl(MethodImplOptions.NoInlining)]
@@ -2503,11 +2691,16 @@ namespace Lucene.Net.Index
 
             try
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     FinishMerges(false);
                     stopMerges = true;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
 
                 if (infoStream.IsEnabled("IW"))
                 {
@@ -2523,14 +2716,15 @@ namespace Lucene.Net.Index
                 bufferedUpdatesStream.Clear();
                 docWriter.Dispose(); // mark it as closed first to prevent subsequent indexing actions/flushes
                 docWriter.Abort(this); // don't sync on IW here
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     if (pendingCommit != null)
                     {
                         pendingCommit.RollbackCommit(directory);
                         deleter.DecRef(pendingCommit);
                         pendingCommit = null;
-                        Monitor.PulseAll(this);
+                        UninterruptableMonitor.PulseAll(this);
                     }
 
                     // Don't bother saving any changes in our segmentInfos
@@ -2569,6 +2763,10 @@ namespace Lucene.Net.Index
                         Debugging.Assert(numDeactivatedThreadStates == docWriter.perThreadPool.MaxThreadStates, "{0} {1}", numDeactivatedThreadStates, docWriter.perThreadPool.MaxThreadStates);
                     }
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
 
                 success = true;
             }
@@ -2585,7 +2783,8 @@ namespace Lucene.Net.Index
                     // e.g. TestIW.testThreadInterruptDeadlock
                     IOUtils.DisposeWhileHandlingException(mergePolicy, mergeScheduler);
                 }
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     if (!success)
                     {
@@ -2611,6 +2810,10 @@ namespace Lucene.Net.Index
                     closed = true;
                     closing = false;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
@@ -2644,7 +2847,8 @@ namespace Lucene.Net.Index
             /* hold the full flush lock to prevent concurrency commits / NRT reopens to
              * get in our way and do unnecessary work. -- if we don't lock this here we might
              * get in trouble if */
-            lock (fullFlushLock)
+            UninterruptableMonitor.Enter(fullFlushLock);
+            try
             {
                 /*
                  * We first abort and trash everything we have in-memory
@@ -2659,7 +2863,8 @@ namespace Lucene.Net.Index
                 {
                     docWriter.LockAndAbortAll(this);
                     ProcessEvents(false, true);
-                    lock (this)
+                    UninterruptableMonitor.Enter(this);
+                    try
                     {
                         try
                         {
@@ -2698,17 +2903,26 @@ namespace Lucene.Net.Index
                             }
                         }
                     }
+                    finally
+                    {
+                        UninterruptableMonitor.Exit(this);
+                    }
                 }
                 finally
                 {
                     docWriter.UnlockAllAfterAbortAll(this);
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(fullFlushLock);
+            }
         }
 
         private void FinishMerges(bool waitForMerges)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (!waitForMerges)
                 {
@@ -2750,7 +2964,7 @@ namespace Lucene.Net.Index
                     }
 
                     stopMerges = false;
-                    Monitor.PulseAll(this);
+                    UninterruptableMonitor.PulseAll(this);
 
                     if (Debugging.AssertsEnabled) Debugging.Assert(0 == mergingSegments.Count);
 
@@ -2769,6 +2983,10 @@ namespace Lucene.Net.Index
                     WaitForMerges();
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -2779,7 +2997,8 @@ namespace Lucene.Net.Index
         /// </summary>
         public virtual void WaitForMerges()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 EnsureOpen(false);
                 if (infoStream.IsEnabled("IW"))
@@ -2799,6 +3018,10 @@ namespace Lucene.Net.Index
                     infoStream.Message("IW", "waitForMerges done");
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -2808,11 +3031,16 @@ namespace Lucene.Net.Index
         /// </summary>
         internal virtual void Checkpoint()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 Changed();
                 deleter.Checkpoint(segmentInfos, false);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -2823,33 +3051,53 @@ namespace Lucene.Net.Index
         /// </summary>
         internal virtual void CheckpointNoSIS()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 changeCount++;
                 deleter.Checkpoint(segmentInfos, false);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
         /// Called internally if any index state has changed. </summary>
         internal void Changed()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 changeCount++;
                 segmentInfos.Changed();
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         internal virtual void PublishFrozenUpdates(FrozenBufferedUpdates packet)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (Debugging.AssertsEnabled) Debugging.Assert(packet != null && packet.Any());
-                lock (bufferedUpdatesStream)
+                UninterruptableMonitor.Enter(bufferedUpdatesStream);
+                try
                 {
                     bufferedUpdatesStream.Push(packet);
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(bufferedUpdatesStream);
+                }
+            }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
             }
         }
 
@@ -2861,10 +3109,12 @@ namespace Lucene.Net.Index
         {
             try
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     // Lock order IW -> BDS
-                    lock (bufferedUpdatesStream)
+                    UninterruptableMonitor.Enter(bufferedUpdatesStream);
+                    try
                     {
                         if (infoStream.IsEnabled("IW"))
                         {
@@ -2896,6 +3146,14 @@ namespace Lucene.Net.Index
                         segmentInfos.Add(newSegment);
                         Checkpoint();
                     }
+                    finally
+                    {
+                        UninterruptableMonitor.Exit(bufferedUpdatesStream);
+                    }
+                }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
                 }
             }
             finally
@@ -2907,11 +3165,16 @@ namespace Lucene.Net.Index
 
         private void ResetMergeExceptions()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 mergeExceptions = new List<MergePolicy.OneMerge>();
                 mergeGen++;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         private void NoDupDirs(params Directory[] dirs)
@@ -3081,7 +3344,8 @@ namespace Lucene.Net.Index
                     }
                 }
 
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     success = false;
                     try
@@ -3111,6 +3375,10 @@ namespace Lucene.Net.Index
                     segmentInfos.AddAll(infos);
                     Checkpoint();
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
 
                 successTop = true;
             }
@@ -3219,10 +3487,15 @@ namespace Lucene.Net.Index
                 {
                     if (!success)
                     {
-                        lock (this)
+                        UninterruptableMonitor.Enter(this);
+                        try
                         {
                             deleter.Refresh(info.Name);
                         }
+                        finally
+                        {
+                            UninterruptableMonitor.Exit(this);
+                        }
                     }
                 }
 
@@ -3234,7 +3507,8 @@ namespace Lucene.Net.Index
                 SetDiagnostics(info, SOURCE_ADDINDEXES_READERS);
 
                 bool useCompoundFile;
-                lock (this) // Guard segmentInfos
+                UninterruptableMonitor.Enter(this); // Guard segmentInfos
+                try
                 {
                     if (stopMerges)
                     {
@@ -3244,6 +3518,10 @@ namespace Lucene.Net.Index
                     EnsureOpen();
                     useCompoundFile = mergePolicy.UseCompoundFile(segmentInfos, infoPerCommit);
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
 
                 // Now create the compound file if needed
                 if (useCompoundFile)
@@ -3257,10 +3535,15 @@ namespace Lucene.Net.Index
                     {
                         // delete new non cfs files directly: they were never
                         // registered with IFD
-                        lock (this)
+                        UninterruptableMonitor.Enter(this);
+                        try
                         {
                             deleter.DeleteNewFiles(filesToDelete);
                         }
+                        finally
+                        {
+                            UninterruptableMonitor.Exit(this);
+                        }
                     }
                     info.UseCompoundFile = true;
                 }
@@ -3279,17 +3562,23 @@ namespace Lucene.Net.Index
                 {
                     if (!success)
                     {
-                        lock (this)
+                        UninterruptableMonitor.Enter(this);
+                        try
                         {
                             deleter.Refresh(info.Name);
                         }
+                        finally
+                        {
+                            UninterruptableMonitor.Exit(this);
+                        }
                     }
                 }
 
                 info.AddFiles(trackingDir.CreatedFiles);
 
                 // Register the new segment
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     if (stopMerges)
                     {
@@ -3300,6 +3589,10 @@ namespace Lucene.Net.Index
                     segmentInfos.Add(infoPerCommit);
                     Checkpoint();
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
             catch (Exception oom) when (oom.IsOutOfMemoryError())
             {
@@ -3502,7 +3795,8 @@ namespace Lucene.Net.Index
 
         private void PrepareCommitInternal()
         {
-            lock (commitLock)
+            UninterruptableMonitor.Enter(commitLock);
+            try
             {
                 EnsureOpen(false);
                 if (infoStream.IsEnabled("IW"))
@@ -3533,7 +3827,8 @@ namespace Lucene.Net.Index
 
                 try
                 {
-                    lock (fullFlushLock)
+                    UninterruptableMonitor.Enter(fullFlushLock);
+                    try
                     {
                         bool flushSuccess = false;
                         bool success = false;
@@ -3549,7 +3844,8 @@ namespace Lucene.Net.Index
                             ProcessEvents(false, true);
                             flushSuccess = true;
 
-                            lock (this)
+                            UninterruptableMonitor.Enter(this);
+                            try
                             {
                                 MaybeApplyDeletes(true);
 
@@ -3572,6 +3868,10 @@ namespace Lucene.Net.Index
                                 filesToCommit = toCommit.GetFiles(directory, false);
                                 deleter.IncRef(filesToCommit);
                             }
+                            finally
+                            {
+                                UninterruptableMonitor.Exit(this);
+                            }
                             success = true;
                         }
                         finally
@@ -3588,6 +3888,10 @@ namespace Lucene.Net.Index
                             DoAfterFlush();
                         }
                     }
+                    finally
+                    {
+                        UninterruptableMonitor.Exit(fullFlushLock);
+                    }
                 }
                 catch (Exception oom) when (oom.IsOutOfMemoryError())
                 {
@@ -3608,7 +3912,8 @@ namespace Lucene.Net.Index
                 {
                     if (!success_)
                     {
-                        lock (this)
+                        UninterruptableMonitor.Enter(this);
+                        try
                         {
                             if (filesToCommit != null)
                             {
@@ -3616,9 +3921,17 @@ namespace Lucene.Net.Index
                                 filesToCommit = null;
                             }
                         }
+                        finally
+                        {
+                            UninterruptableMonitor.Exit(this);
+                        }
                     }
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(commitLock);
+            }
         }
 
         /// <summary>
@@ -3633,11 +3946,16 @@ namespace Lucene.Net.Index
         /// </summary>
         public void SetCommitData(IDictionary<string, string> commitUserData)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 segmentInfos.UserData = new Dictionary<string, string>(commitUserData);
                 ++changeCount;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -3648,10 +3966,15 @@ namespace Lucene.Net.Index
         {
             get
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     return segmentInfos.UserData;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
@@ -3717,7 +4040,8 @@ namespace Lucene.Net.Index
                 infoStream.Message("IW", "commit: start");
             }
 
-            lock (commitLock)
+            UninterruptableMonitor.Enter(commitLock);
+            try
             {
                 EnsureOpen(false);
 
@@ -3744,11 +4068,16 @@ namespace Lucene.Net.Index
 
                 FinishCommit();
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(commitLock);
+            }
         }
 
         private void FinishCommit()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (pendingCommit != null)
                 {
@@ -3776,7 +4105,7 @@ namespace Lucene.Net.Index
                         deleter.DecRef(filesToCommit);
                         filesToCommit = null;
                         pendingCommit = null;
-                        Monitor.PulseAll(this);
+                        UninterruptableMonitor.PulseAll(this);
                     }
                 }
                 else
@@ -3792,6 +4121,10 @@ namespace Lucene.Net.Index
                     infoStream.Message("IW", "commit: done");
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -3801,7 +4134,7 @@ namespace Lucene.Net.Index
         private readonly object fullFlushLock = new object();
 
         // for assert
-        internal virtual bool HoldsFullFlushLock => Monitor.IsEntered(fullFlushLock);
+        internal virtual bool HoldsFullFlushLock => UninterruptableMonitor.IsEntered(fullFlushLock);
 
         /// <summary>
         /// Flush all in-memory buffered updates (adds and deletes)
@@ -3847,7 +4180,8 @@ namespace Lucene.Net.Index
                 }
                 bool anySegmentFlushed;
 
-                lock (fullFlushLock)
+                UninterruptableMonitor.Enter(fullFlushLock);
+                try
                 {
                     bool flushSuccess = false;
                     try
@@ -3861,7 +4195,12 @@ namespace Lucene.Net.Index
                         ProcessEvents(false, true);
                     }
                 }
-                lock (this)
+                finally
+                {
+                    UninterruptableMonitor.Exit(fullFlushLock);
+                }
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     MaybeApplyDeletes(applyAllDeletes);
                     DoAfterFlush();
@@ -3873,6 +4212,10 @@ namespace Lucene.Net.Index
                     success = true;
                     return anySegmentFlushed;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
             catch (Exception oom) when (oom.IsOutOfMemoryError())
             {
@@ -3894,7 +4237,8 @@ namespace Lucene.Net.Index
 
         internal void MaybeApplyDeletes(bool applyAllDeletes)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (applyAllDeletes)
                 {
@@ -3909,11 +4253,16 @@ namespace Lucene.Net.Index
                     infoStream.Message("IW", "don't apply deletes now delTermCount=" + bufferedUpdatesStream.NumTerms + " bytesUsed=" + bufferedUpdatesStream.BytesUsed);
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         internal void ApplyAllDeletesAndUpdates()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 flushDeletesCount.IncrementAndGet();
                 BufferedUpdatesStream.ApplyDeletesResult result;
@@ -3944,6 +4293,10 @@ namespace Lucene.Net.Index
                 }
                 bufferedUpdatesStream.Prune(segmentInfos);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -3966,16 +4319,22 @@ namespace Lucene.Net.Index
         /// </summary>
         public int NumRamDocs()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 EnsureOpen();
                 return docWriter.NumDocs;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         private void EnsureValidMerge(MergePolicy.OneMerge merge)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 foreach (SegmentCommitInfo info in merge.Segments)
                 {
@@ -3985,6 +4344,10 @@ namespace Lucene.Net.Index
                     }
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         private static void SkipDeletedDoc(DocValuesFieldUpdates.Iterator[] updatesIters, int deletedDoc) // LUCENENET: CA1822: Mark members as static
@@ -4067,7 +4430,8 @@ namespace Lucene.Net.Index
         /// </summary>
         private ReadersAndUpdates CommitMergedDeletesAndUpdates(MergePolicy.OneMerge merge, MergeState mergeState)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (Debugging.AssertsEnabled) Debugging.Assert(TestPoint("startCommitMergeDeletes"));
 
@@ -4095,7 +4459,7 @@ namespace Lucene.Net.Index
                     IBits prevLiveDocs = merge.readers[i].LiveDocs;
                     ReadersAndUpdates rld = readerPool.Get(info, false);
                     // We hold a ref so it should still be in the pool:
-                    if (Debugging.AssertsEnabled) Debugging.Assert(rld != null,"seg={0}", info.Info.Name);
+                    if (Debugging.AssertsEnabled) Debugging.Assert(rld != null, "seg={0}", info.Info.Name);
                     IBits currentLiveDocs = rld.LiveDocs;
                     IDictionary<string, DocValuesFieldUpdates> mergingFieldUpdates = rld.MergingFieldUpdates;
                     string[] mergingFields;
@@ -4302,11 +4666,16 @@ namespace Lucene.Net.Index
 
                 return holder.mergedDeletesAndUpdates;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         private bool CommitMerge(MergePolicy.OneMerge merge, MergeState mergeState)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (Debugging.AssertsEnabled) Debugging.Assert(TestPoint("startCommitMerge"));
 
@@ -4463,6 +4832,10 @@ namespace Lucene.Net.Index
 
                 return true;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         private void HandleMergeException(Exception t, MergePolicy.OneMerge merge)
@@ -4537,7 +4910,8 @@ namespace Lucene.Net.Index
                 }
                 finally
                 {
-                    lock (this)
+                    UninterruptableMonitor.Enter(this);
+                    try
                     {
                         MergeFinish(merge);
 
@@ -4561,6 +4935,10 @@ namespace Lucene.Net.Index
                             UpdatePendingMerges(MergeTrigger.MERGE_FINISHED, merge.MaxNumSegments);
                         }
                     }
+                    finally
+                    {
+                        UninterruptableMonitor.Exit(this);
+                    }
                 }
             }
             catch (Exception oom) when (oom.IsOutOfMemoryError())
@@ -4592,7 +4970,8 @@ namespace Lucene.Net.Index
         /// </summary>
         internal bool RegisterMerge(MergePolicy.OneMerge merge)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (merge.registerDone)
                 {
@@ -4697,6 +5076,10 @@ namespace Lucene.Net.Index
 
                 return true;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -4705,7 +5088,8 @@ namespace Lucene.Net.Index
         /// </summary>
         internal void MergeInit(MergePolicy.OneMerge merge)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 bool success = false;
                 try
@@ -4725,11 +5109,16 @@ namespace Lucene.Net.Index
                     }
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         private void MergeInitImpl(MergePolicy.OneMerge merge) // LUCENENET specific: renamed from _mergeInit
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (Debugging.AssertsEnabled)
                 {
@@ -4810,6 +5199,10 @@ namespace Lucene.Net.Index
                     infoStream.Message("IW", "merge seg=" + merge.info.Info.Name + " " + SegString(merge.Segments));
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         internal static void SetDiagnostics(SegmentInfo info, string source)
@@ -4843,11 +5236,12 @@ namespace Lucene.Net.Index
         /// </summary>
         public void MergeFinish(MergePolicy.OneMerge merge)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 // forceMerge, addIndexes or finishMerges may be waiting
                 // on merges to finish.
-                Monitor.PulseAll(this);
+                UninterruptableMonitor.PulseAll(this);
 
                 // It's possible we are called twice, eg if there was an
                 // exception inside mergeInit
@@ -4863,11 +5257,16 @@ namespace Lucene.Net.Index
 
                 runningMerges.Remove(merge);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         private void CloseMergeReaders(MergePolicy.OneMerge merge, bool suppressExceptions)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 int numSegments = merge.readers.Count;
                 Exception th = null;
@@ -4916,6 +5315,10 @@ namespace Lucene.Net.Index
                     IOUtils.ReThrow(th);
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -4962,7 +5365,8 @@ namespace Lucene.Net.Index
                     IBits liveDocs;
                     int delCount;
 
-                    lock (this)
+                    UninterruptableMonitor.Enter(this);
+                    try
                     {
                         // Must sync to ensure BufferedDeletesStream cannot change liveDocs,
                         // pendingDeleteCount and field updates while we pull a copy:
@@ -4992,6 +5396,10 @@ namespace Lucene.Net.Index
                             }
                         }
                     }
+                    finally
+                    {
+                        UninterruptableMonitor.Exit(this);
+                    }
 
                     // Deletes might have happened after we pulled the merge reader and
                     // before we got a read-only copy of the segment's actual live docs
@@ -5053,10 +5461,15 @@ namespace Lucene.Net.Index
                 {
                     if (!success3)
                     {
-                        lock (this)
+                        UninterruptableMonitor.Enter(this);
+                        try
                         {
                             deleter.Refresh(merge.info.Info.Name);
                         }
+                        finally
+                        {
+                            UninterruptableMonitor.Exit(this);
+                        }
                     }
                 }
                 if (Debugging.AssertsEnabled) Debugging.Assert(mergeState.SegmentInfo == merge.info.Info);
@@ -5081,10 +5494,15 @@ namespace Lucene.Net.Index
                 // this segment:
                 //System.out.println("merger set hasProx=" + merger.hasProx() + " seg=" + merge.info.name);
                 bool useCompoundFile;
-                lock (this) // Guard segmentInfos
+                UninterruptableMonitor.Enter(this); // Guard segmentInfos
+                try
                 {
                     useCompoundFile = mergePolicy.UseCompoundFile(segmentInfos, merge.info);
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
 
                 if (useCompoundFile)
                 {
@@ -5099,7 +5517,8 @@ namespace Lucene.Net.Index
                     }
                     catch (Exception ioe) when (ioe.IsIOException())
                     {
-                        lock (this)
+                        UninterruptableMonitor.Enter(this);
+                        try
                         {
                             if (merge.IsAborted)
                             {
@@ -5112,6 +5531,10 @@ namespace Lucene.Net.Index
                                 HandleMergeException(ioe, merge);
                             }
                         }
+                        finally
+                        {
+                            UninterruptableMonitor.Exit(this);
+                        }
                     }
                     catch (Exception t) when (t.IsThrowable())
                     {
@@ -5126,12 +5549,17 @@ namespace Lucene.Net.Index
                                 infoStream.Message("IW", "hit exception creating compound file during merge");
                             }
 
-                            lock (this)
+                            UninterruptableMonitor.Enter(this);
+                            try
                             {
                                 deleter.DeleteFile(Lucene.Net.Index.IndexFileNames.SegmentFileName(mergedName, "", Lucene.Net.Index.IndexFileNames.COMPOUND_FILE_EXTENSION));
                                 deleter.DeleteFile(Lucene.Net.Index.IndexFileNames.SegmentFileName(mergedName, "", Lucene.Net.Index.IndexFileNames.COMPOUND_FILE_ENTRIES_EXTENSION));
                                 deleter.DeleteNewFiles(merge.info.GetFiles());
                             }
+                            finally
+                            {
+                                UninterruptableMonitor.Exit(this);
+                            }
                         }
                     }
 
@@ -5140,7 +5568,8 @@ namespace Lucene.Net.Index
                     // per-segment readers in the finally clause below:
                     success = false;
 
-                    lock (this)
+                    UninterruptableMonitor.Enter(this);
+                    try
                     {
                         // delete new non cfs files directly: they were never
                         // registered with IFD
@@ -5157,6 +5586,10 @@ namespace Lucene.Net.Index
                             return 0;
                         }
                     }
+                    finally
+                    {
+                        UninterruptableMonitor.Exit(this);
+                    }
 
                     merge.info.Info.UseCompoundFile = true;
                 }
@@ -5182,10 +5615,15 @@ namespace Lucene.Net.Index
                 {
                     if (!success2)
                     {
-                        lock (this)
+                        UninterruptableMonitor.Enter(this);
+                        try
                         {
                             deleter.DeleteNewFiles(merge.info.GetFiles());
                         }
+                        finally
+                        {
+                            UninterruptableMonitor.Exit(this);
+                        }
                     }
                 }
 
@@ -5209,11 +5647,16 @@ namespace Lucene.Net.Index
                     }
                     finally
                     {
-                        lock (this)
+                        UninterruptableMonitor.Enter(this);
+                        try
                         {
                             rld.Release(sr);
                             readerPool.Release(rld);
                         }
+                        finally
+                        {
+                            UninterruptableMonitor.Exit(this);
+                        }
                     }
                 }
 
@@ -5243,7 +5686,8 @@ namespace Lucene.Net.Index
 
         internal virtual void AddMergeException(MergePolicy.OneMerge merge)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (Debugging.AssertsEnabled) Debugging.Assert(merge.Exception != null);
                 if (!mergeExceptions.Contains(merge) && mergeGen == merge.mergeGen)
@@ -5251,6 +5695,10 @@ namespace Lucene.Net.Index
                     mergeExceptions.Add(merge);
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         // For test purposes.
@@ -5262,10 +5710,15 @@ namespace Lucene.Net.Index
         // utility routines for tests
         internal virtual SegmentCommitInfo NewestSegment()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 return segmentInfos.Count > 0 ? segmentInfos.Info(segmentInfos.Count - 1) : null;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -5276,10 +5729,15 @@ namespace Lucene.Net.Index
         /// </summary>
         public virtual string SegString()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 return SegString(segmentInfos.Segments);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -5290,7 +5748,8 @@ namespace Lucene.Net.Index
         /// </summary>
         public virtual string SegString(IEnumerable<SegmentCommitInfo> infos)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 StringBuilder buffer = new StringBuilder();
                 foreach (SegmentCommitInfo info in infos)
@@ -5303,6 +5762,10 @@ namespace Lucene.Net.Index
                 }
                 return buffer.ToString();
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -5313,15 +5776,21 @@ namespace Lucene.Net.Index
         /// </summary>
         public virtual string SegString(SegmentCommitInfo info)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 return info.ToString(info.Info.Dir, NumDeletedDocs(info) - info.DelCount);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         private void DoWait()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 // NOTE: the callers of this method should in theory
                 // be able to do simply wait(), but, as a defense
@@ -5331,13 +5800,17 @@ namespace Lucene.Net.Index
                 // conditions are satisfied:
                 try
                 {
-                    Monitor.Wait(this, TimeSpan.FromMilliseconds(1000));
+                    UninterruptableMonitor.Wait(this, TimeSpan.FromMilliseconds(1000));
                 }
                 catch (Exception ie) when (ie.IsInterruptedException())
                 {
                     throw new Util.ThreadInterruptedException(ie);
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         private bool keepFullyDeletedSegments;
@@ -5377,7 +5850,8 @@ namespace Lucene.Net.Index
         // For infoStream output
         internal virtual SegmentInfos ToLiveInfos(SegmentInfos sis)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 SegmentInfos newSIS = new SegmentInfos();
                 IDictionary<SegmentCommitInfo, SegmentCommitInfo> liveSIS = new Dictionary<SegmentCommitInfo, SegmentCommitInfo>();
@@ -5397,6 +5871,10 @@ namespace Lucene.Net.Index
 
                 return newSIS;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -5426,7 +5904,8 @@ namespace Lucene.Net.Index
                     infoStream.Message("IW", "StartCommit(): start");
                 }
 
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     if (Debugging.AssertsEnabled) Debugging.Assert(lastCommitChangeCount <= changeCount,"lastCommitChangeCount={0} changeCount={1}", lastCommitChangeCount, changeCount);
 
@@ -5448,6 +5927,10 @@ namespace Lucene.Net.Index
 
                     if (Debugging.AssertsEnabled) Debugging.Assert(FilesExist(toSync));
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
 
                 if (Debugging.AssertsEnabled) Debugging.Assert(TestPoint("midStartCommit"));
 
@@ -5457,7 +5940,8 @@ namespace Lucene.Net.Index
                 {
                     if (Debugging.AssertsEnabled) Debugging.Assert(TestPoint("midStartCommit2"));
 
-                    lock (this)
+                    UninterruptableMonitor.Enter(this);
+                    try
                     {
                         if (Debugging.AssertsEnabled) Debugging.Assert(pendingCommit == null);
 
@@ -5472,6 +5956,10 @@ namespace Lucene.Net.Index
                         pendingCommitSet = true;
                         pendingCommit = toSync;
                     }
+                    finally
+                    {
+                        UninterruptableMonitor.Exit(this);
+                    }
 
                     // this call can take a long time -- 10s of seconds
                     // or more.  We do it without syncing on this:
@@ -5502,7 +5990,8 @@ namespace Lucene.Net.Index
                 }
                 finally
                 {
-                    lock (this)
+                    UninterruptableMonitor.Enter(this);
+                    try
                     {
                         // Have our master segmentInfos record the
                         // generations we just prepared.  We do this
@@ -5522,6 +6011,10 @@ namespace Lucene.Net.Index
                             filesToCommit = null;
                         }
                     }
+                    finally
+                    {
+                        UninterruptableMonitor.Exit(this);
+                    }
                 }
             }
             catch (Exception oom) when (oom.IsOutOfMemoryError())
@@ -5618,7 +6111,8 @@ namespace Lucene.Net.Index
 
         internal virtual bool NrtIsCurrent(SegmentInfos infos)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 //System.out.println("IW.nrtIsCurrent " + (infos.version == segmentInfos.version && !docWriter.anyChanges() && !bufferedDeletesStream.any()));
                 EnsureOpen();
@@ -5628,16 +6122,25 @@ namespace Lucene.Net.Index
                 }
                 return infos.Version == segmentInfos.Version && !docWriter.AnyChanges() && !bufferedUpdatesStream.Any();
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         public virtual bool IsClosed
         {
             get
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     return closed;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
@@ -5669,12 +6172,17 @@ namespace Lucene.Net.Index
         /// </summary>
         public virtual void DeleteUnusedFiles()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 EnsureOpen(false);
                 deleter.DeletePendingFiles();
                 deleter.RevisitPolicy();
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         // LUCENENET specific - DeletePendingFiles() excluded because it is not referenced - IDE0051
@@ -5752,10 +6260,15 @@ namespace Lucene.Net.Index
         /// <seealso cref="IndexFileDeleter.DeleteNewFiles(ICollection{string})"/>
         internal void DeleteNewFiles(ICollection<string> files)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 deleter.DeleteNewFiles(files);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -5763,10 +6276,15 @@ namespace Lucene.Net.Index
         /// <seealso cref="IndexFileDeleter.Refresh(string)"/>
         internal void FlushFailed(SegmentInfo info)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 deleter.Refresh(info.Name);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         internal int Purge(bool forced)
@@ -5804,20 +6322,30 @@ namespace Lucene.Net.Index
 
         internal virtual void IncRefDeleter(SegmentInfos segmentInfos)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 EnsureOpen();
                 deleter.IncRef(segmentInfos, false);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         internal virtual void DecRefDeleter(SegmentInfos segmentInfos)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 EnsureOpen();
                 deleter.DecRef(segmentInfos);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         private bool ProcessEvents(bool triggerMerge, bool forcePurge)
diff --git a/src/Lucene.Net/Index/MergePolicy.cs b/src/Lucene.Net/Index/MergePolicy.cs
index cf6f5ac..606e36c 100644
--- a/src/Lucene.Net/Index/MergePolicy.cs
+++ b/src/Lucene.Net/Index/MergePolicy.cs
@@ -1,5 +1,6 @@
 using J2N.Collections.Generic.Extensions;
 using Lucene.Net.Diagnostics;
+using Lucene.Net.Support.Threading;
 using Lucene.Net.Util;
 using System;
 using System.Collections.Generic;
@@ -229,17 +230,27 @@ namespace Lucene.Net.Index
             {
                 set
                 {
-                    lock (this)
+                    UninterruptableMonitor.Enter(this);
+                    try
                     {
                         this.error = value;
                     }
+                    finally
+                    {
+                        UninterruptableMonitor.Exit(this);
+                    }
                 }
                 get
                 {
-                    lock (this)
+                    UninterruptableMonitor.Enter(this);
+                    try
                     {
                         return error;
                     }
+                    finally
+                    {
+                        UninterruptableMonitor.Exit(this);
+                    }
                 }
             }
 
@@ -251,10 +262,15 @@ namespace Lucene.Net.Index
             [MethodImpl(MethodImplOptions.NoInlining)]
             internal virtual void Abort()
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     aborted = true;
-                    Monitor.PulseAll(this);
+                    UninterruptableMonitor.PulseAll(this);
+                }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
                 }
             }
 
@@ -264,10 +280,15 @@ namespace Lucene.Net.Index
             {
                 get
                 {
-                    lock (this)
+                    UninterruptableMonitor.Enter(this);
+                    try
                     {
                         return aborted;
                     }
+                    finally
+                    {
+                        UninterruptableMonitor.Exit(this);
+                    }
                 }
             }
 
@@ -277,7 +298,8 @@ namespace Lucene.Net.Index
             /// </summary>
             public virtual void CheckAborted(Directory dir)
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     if (aborted)
                     {
@@ -290,7 +312,7 @@ namespace Lucene.Net.Index
                         {
                             //In theory we could wait() indefinitely, but we
                             // do 1000 msec, defensively
-                            Monitor.Wait(this, TimeSpan.FromMilliseconds(1000));
+                            UninterruptableMonitor.Wait(this, TimeSpan.FromMilliseconds(1000));
                         }
                         catch (Exception ie) when (ie.IsInterruptedException())
                         {
@@ -303,6 +325,10 @@ namespace Lucene.Net.Index
                         }
                     }
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
 
             /// <summary>
@@ -312,15 +338,20 @@ namespace Lucene.Net.Index
             /// </summary>
             internal virtual void SetPause(bool paused)
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     this.paused = paused;
                     if (!paused)
                     {
                         // Wakeup merge thread, if it's waiting
-                        Monitor.PulseAll(this);
+                        UninterruptableMonitor.PulseAll(this);
                     }
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
 
             /// <summary>
@@ -331,10 +362,15 @@ namespace Lucene.Net.Index
             {
                 get
                 {
-                    lock (this)
+                    UninterruptableMonitor.Enter(this);
+                    try
                     {
                         return paused;
                     }
+                    finally
+                    {
+                        UninterruptableMonitor.Exit(this);
+                    }
                 }
             }
 
diff --git a/src/Lucene.Net/Index/MultiReader.cs b/src/Lucene.Net/Index/MultiReader.cs
index acbdd14..dd4d090 100644
--- a/src/Lucene.Net/Index/MultiReader.cs
+++ b/src/Lucene.Net/Index/MultiReader.cs
@@ -1,4 +1,5 @@
-using System;
+using Lucene.Net.Support.Threading;
+using System;
 using System.IO;
 using System.Runtime.ExceptionServices;
 
@@ -73,7 +74,8 @@ namespace Lucene.Net.Index
 
         protected internal override void DoClose()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 Exception ioe = null; // LUCENENET: No need to cast to IOExcpetion
                 foreach (IndexReader r in GetSequentialSubReaders())
@@ -103,6 +105,10 @@ namespace Lucene.Net.Index
                     ExceptionDispatchInfo.Capture(ioe).Throw(); // LUCENENET: Rethrow to preserve stack details from the original throw
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
     }
 }
\ No newline at end of file
diff --git a/src/Lucene.Net/Index/ParallelAtomicReader.cs b/src/Lucene.Net/Index/ParallelAtomicReader.cs
index d9db780..8199766 100644
--- a/src/Lucene.Net/Index/ParallelAtomicReader.cs
+++ b/src/Lucene.Net/Index/ParallelAtomicReader.cs
@@ -1,5 +1,6 @@
 using J2N.Runtime.CompilerServices;
 using Lucene.Net.Support;
+using Lucene.Net.Support.Threading;
 using System;
 using System.Collections.Generic;
 using System.IO;
@@ -284,7 +285,8 @@ namespace Lucene.Net.Index
 
         protected internal override void DoClose()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 Exception ioe = null; // LUCENENET: No need to cast to IOExcpetion
                 foreach (AtomicReader reader in completeReaderSet)
@@ -314,6 +316,10 @@ namespace Lucene.Net.Index
                     ExceptionDispatchInfo.Capture(ioe).Throw(); // LUCENENET: Rethrow to preserve stack details from the original throw
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         public override NumericDocValues GetNumericDocValues(string field)
diff --git a/src/Lucene.Net/Index/ParallelCompositeReader.cs b/src/Lucene.Net/Index/ParallelCompositeReader.cs
index 9ada68a..437c0a8 100644
--- a/src/Lucene.Net/Index/ParallelCompositeReader.cs
+++ b/src/Lucene.Net/Index/ParallelCompositeReader.cs
@@ -1,6 +1,7 @@
 using J2N.Runtime.CompilerServices;
 using Lucene.Net.Diagnostics;
 using Lucene.Net.Support;
+using Lucene.Net.Support.Threading;
 using System;
 using System.Collections.Generic;
 using System.IO;
@@ -222,7 +223,8 @@ namespace Lucene.Net.Index
 
         protected internal override void DoClose()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 Exception ioe = null; // LUCENENET: No need to cast to IOExcpetion
                 foreach (IndexReader reader in completeReaderSet)
@@ -252,6 +254,10 @@ namespace Lucene.Net.Index
                     ExceptionDispatchInfo.Capture(ioe).Throw(); // LUCENENET: Rethrow to preserve stack details from the original throw
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
     }
 }
\ No newline at end of file
diff --git a/src/Lucene.Net/Index/PersistentSnapshotDeletionPolicy.cs b/src/Lucene.Net/Index/PersistentSnapshotDeletionPolicy.cs
index f9bcdb9..1688718 100644
--- a/src/Lucene.Net/Index/PersistentSnapshotDeletionPolicy.cs
+++ b/src/Lucene.Net/Index/PersistentSnapshotDeletionPolicy.cs
@@ -1,4 +1,5 @@
 using Lucene.Net.Support;
+using Lucene.Net.Support.Threading;
 using System;
 using System.Collections.Generic;
 using System.Globalization;
@@ -124,7 +125,8 @@ namespace Lucene.Net.Index
         /// <seealso cref="SnapshotDeletionPolicy.Snapshot()"/>
         public override IndexCommit Snapshot()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 IndexCommit ic = base.Snapshot();
                 bool success = false;
@@ -149,6 +151,10 @@ namespace Lucene.Net.Index
                 }
                 return ic;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -158,7 +164,8 @@ namespace Lucene.Net.Index
         /// <seealso cref="SnapshotDeletionPolicy.Release(IndexCommit)"/>
         public override void Release(IndexCommit commit)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 base.Release(commit);
                 bool success = false;
@@ -182,6 +189,10 @@ namespace Lucene.Net.Index
                     }
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -192,17 +203,23 @@ namespace Lucene.Net.Index
         /// <seealso cref="SnapshotDeletionPolicy.Release(IndexCommit)"/>
         public virtual void Release(long gen)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 base.ReleaseGen(gen);
                 Persist();
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         [MethodImpl(MethodImplOptions.NoInlining)]
         internal void Persist()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 string fileName = SNAPSHOTS_PREFIX + nextWriteGen;
                 IndexOutput @out = dir.CreateOutput(fileName, IOContext.DEFAULT);
@@ -255,11 +272,16 @@ namespace Lucene.Net.Index
 
                 nextWriteGen++;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         private void ClearPriorSnapshots()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 foreach (string file in dir.ListAll())
                 {
@@ -269,6 +291,10 @@ namespace Lucene.Net.Index
                     }
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -298,7 +324,8 @@ namespace Lucene.Net.Index
         /// </summary>
         private void LoadPriorSnapshots()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 long genLoaded = -1;
                 Exception ioe = null; // LUCENENET: No need to cast to IOExcpetion
@@ -371,6 +398,10 @@ namespace Lucene.Net.Index
                     nextWriteGen = 1 + genLoaded;
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
     }
 }
\ No newline at end of file
diff --git a/src/Lucene.Net/Index/ReadersAndUpdates.cs b/src/Lucene.Net/Index/ReadersAndUpdates.cs
index 6cd440a..8dcfde1 100644
--- a/src/Lucene.Net/Index/ReadersAndUpdates.cs
+++ b/src/Lucene.Net/Index/ReadersAndUpdates.cs
@@ -1,6 +1,7 @@
 using J2N.Threading.Atomic;
 using Lucene.Net.Diagnostics;
 using Lucene.Net.Documents;
+using Lucene.Net.Support.Threading;
 using System;
 using System.Collections.Generic;
 using System.Globalization;
@@ -125,17 +126,23 @@ namespace Lucene.Net.Index
         {
             get
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     return pendingDeleteCount;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
         // Call only from assert!
         public virtual bool VerifyDocCounts()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 int count;
                 if (liveDocs != null)
@@ -157,6 +164,10 @@ namespace Lucene.Net.Index
                 if (Debugging.AssertsEnabled) Debugging.Assert(Info.Info.DocCount - Info.DelCount - pendingDeleteCount == count, "info.docCount={0} info.DelCount={1} pendingDeleteCount={2} count={3}", Info.Info.DocCount, Info.DelCount, pendingDeleteCount, count);
                 return true;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -182,7 +193,8 @@ namespace Lucene.Net.Index
         // index):
         public virtual SegmentReader GetMergeReader(IOContext context)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 //System.out.println("  livedocs=" + rld.liveDocs);
 
@@ -215,25 +227,35 @@ namespace Lucene.Net.Index
                 mergeReader.IncRef();
                 return mergeReader;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         public virtual void Release(SegmentReader sr)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (Debugging.AssertsEnabled) Debugging.Assert(Info == sr.SegmentInfo);
                 sr.DecRef();
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         public virtual bool Delete(int docID)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (Debugging.AssertsEnabled)
                 {
                     Debugging.Assert(liveDocs != null);
-                    Debugging.Assert(Monitor.IsEntered(writer));
+                    Debugging.Assert(UninterruptableMonitor.IsEntered(writer));
                     Debugging.Assert(docID >= 0 && docID < liveDocs.Length, "out of bounds: docid={0} liveDocsLength={1} seg={2} docCount={3}", docID, liveDocs.Length, Info.Info.Name, Info.Info.DocCount);
                     Debugging.Assert(!liveDocsShared);
                 }
@@ -246,12 +268,17 @@ namespace Lucene.Net.Index
                 }
                 return didDelete;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         // NOTE: removes callers ref
         public virtual void DropReaders()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 // TODO: can we somehow use IOUtils here...?  problem is
                 // we are calling .decRef not .close)...
@@ -288,6 +315,10 @@ namespace Lucene.Net.Index
 
                 DecRef();
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -297,7 +328,8 @@ namespace Lucene.Net.Index
         [MethodImpl(MethodImplOptions.NoInlining)]
         public virtual SegmentReader GetReadOnlyClone(IOContext context)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (reader == null)
                 {
@@ -316,15 +348,20 @@ namespace Lucene.Net.Index
                     return reader;
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         public virtual void InitWritableLiveDocs()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (Debugging.AssertsEnabled)
                 {
-                    Debugging.Assert(Monitor.IsEntered(writer));
+                    Debugging.Assert(UninterruptableMonitor.IsEntered(writer));
                     Debugging.Assert(Info.Info.DocCount > 0);
                 }
                 //System.out.println("initWritableLivedocs seg=" + info + " liveDocs=" + liveDocs + " shared=" + shared);
@@ -347,37 +384,52 @@ namespace Lucene.Net.Index
                     liveDocsShared = false;
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         public virtual IBits LiveDocs
         {
             get
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
-                    if (Debugging.AssertsEnabled) Debugging.Assert(Monitor.IsEntered(writer));
+                    if (Debugging.AssertsEnabled) Debugging.Assert(UninterruptableMonitor.IsEntered(writer));
                     return liveDocs;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
         public virtual IBits GetReadOnlyLiveDocs()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 //System.out.println("getROLiveDocs seg=" + info);
-                if (Debugging.AssertsEnabled) Debugging.Assert(Monitor.IsEntered(writer));
+                if (Debugging.AssertsEnabled) Debugging.Assert(UninterruptableMonitor.IsEntered(writer));
                 liveDocsShared = true;
                 //if (liveDocs != null) {
                 //System.out.println("  liveCount=" + liveDocs.count());
                 //}
                 return liveDocs;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         public virtual void DropChanges()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 // Discard (don't save) changes when we are dropping
                 // the reader; this is used only on the sub-readers
@@ -389,6 +441,10 @@ namespace Lucene.Net.Index
                 pendingDeleteCount = 0;
                 DropMergingUpdates();
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         // Commit live docs (writes new _X_N.del files) and field updates (writes new
@@ -398,9 +454,10 @@ namespace Lucene.Net.Index
         [MethodImpl(MethodImplOptions.NoInlining)]
         public virtual bool WriteLiveDocs(Directory dir)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
-                if (Debugging.AssertsEnabled) Debugging.Assert(Monitor.IsEntered(writer));
+                if (Debugging.AssertsEnabled) Debugging.Assert(UninterruptableMonitor.IsEntered(writer));
                 //System.out.println("rld.writeLiveDocs seg=" + info + " pendingDelCount=" + pendingDeleteCount + " numericUpdates=" + numericUpdates);
                 if (pendingDeleteCount == 0)
                 {
@@ -457,15 +514,20 @@ namespace Lucene.Net.Index
 
                 return true;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         // Writes field updates (new _X_N updates files) to the directory
         [MethodImpl(MethodImplOptions.NoInlining)]
         public virtual void WriteFieldUpdates(Directory dir, DocValuesFieldUpdates.Container dvUpdates)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
-                if (Debugging.AssertsEnabled) Debugging.Assert(Monitor.IsEntered(writer));
+                if (Debugging.AssertsEnabled) Debugging.Assert(UninterruptableMonitor.IsEntered(writer));
                 //System.out.println("rld.writeFieldUpdates: seg=" + info + " numericFieldUpdates=" + numericFieldUpdates);
 
                 if (Debugging.AssertsEnabled) Debugging.Assert(dvUpdates.Any());
@@ -674,6 +736,10 @@ namespace Lucene.Net.Index
                     }
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -751,9 +817,10 @@ namespace Lucene.Net.Index
         /// </summary>
         internal virtual SegmentReader GetReaderForMerge(IOContext context)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
-                if (Debugging.AssertsEnabled) Debugging.Assert(Monitor.IsEntered(writer));
+                if (Debugging.AssertsEnabled) Debugging.Assert(UninterruptableMonitor.IsEntered(writer));
                 // must execute these two statements as atomic operation, otherwise we
                 // could lose updates if e.g. another thread calls writeFieldUpdates in
                 // between, or the updates are applied to the obtained reader, but then
@@ -762,6 +829,10 @@ namespace Lucene.Net.Index
                 isMerging = true;
                 return GetReader(context);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -770,11 +841,16 @@ namespace Lucene.Net.Index
         /// </summary>
         public virtual void DropMergingUpdates()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 mergingDVUpdates.Clear();
                 isMerging = false;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -783,10 +859,15 @@ namespace Lucene.Net.Index
         {
             get
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     return mergingDVUpdates;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
diff --git a/src/Lucene.Net/Index/SegmentCoreReaders.cs b/src/Lucene.Net/Index/SegmentCoreReaders.cs
index 0a88cb7..dda954c 100644
--- a/src/Lucene.Net/Index/SegmentCoreReaders.cs
+++ b/src/Lucene.Net/Index/SegmentCoreReaders.cs
@@ -1,8 +1,10 @@
 using J2N.Threading.Atomic;
 using Lucene.Net.Diagnostics;
 using Lucene.Net.Support;
+using Lucene.Net.Support.Threading;
 using Lucene.Net.Util;
 using System;
+using System.Collections;
 using System.Collections.Generic;
 using JCG = J2N.Collections.Generic;
 
@@ -195,7 +197,9 @@ namespace Lucene.Net.Index
 
         private void NotifyCoreClosedListeners(Exception th)
         {
-            lock (coreClosedListeners)
+            object syncRoot = ((ICollection)coreClosedListeners).SyncRoot;
+            UninterruptableMonitor.Enter(syncRoot);
+            try
             {
                 foreach (ICoreDisposedListener listener in coreClosedListeners)
                 {
@@ -219,6 +223,10 @@ namespace Lucene.Net.Index
                 }
                 IOUtils.ReThrowUnchecked(th);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(syncRoot);
+            }
         }
 
         internal void AddCoreDisposedListener(ICoreDisposedListener listener)
diff --git a/src/Lucene.Net/Index/SegmentDocValues.cs b/src/Lucene.Net/Index/SegmentDocValues.cs
index 94b6b56..d150f4f 100644
--- a/src/Lucene.Net/Index/SegmentDocValues.cs
+++ b/src/Lucene.Net/Index/SegmentDocValues.cs
@@ -1,5 +1,6 @@
 using J2N.Collections.Generic.Extensions;
 using Lucene.Net.Diagnostics;
+using Lucene.Net.Support.Threading;
 using Lucene.Net.Util;
 using System;
 using System.Collections.Generic;
@@ -68,10 +69,15 @@ namespace Lucene.Net.Index
             protected override void Release()
             {
                 m_object.Dispose();
-                lock (outerInstance)
+                UninterruptableMonitor.Enter(outerInstance);
+                try
                 {
                     outerInstance.genDVProducers.Remove(gen);
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(outerInstance);
+                }
             }
         }
 
@@ -79,7 +85,8 @@ namespace Lucene.Net.Index
         /// Returns the <see cref="DocValuesProducer"/> for the given generation. </summary>
         internal DocValuesProducer GetDocValuesProducer(long? gen, SegmentCommitInfo si, IOContext context, Directory dir, DocValuesFormat dvFormat, IList<FieldInfo> infos, int termsIndexDivisor)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (!genDVProducers.TryGetValue(gen, out RefCount<DocValuesProducer> dvp))
                 {
@@ -93,6 +100,10 @@ namespace Lucene.Net.Index
                 }
                 return dvp.Get();
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -101,7 +112,8 @@ namespace Lucene.Net.Index
         /// </summary>
         internal void DecRef(IList<long?> dvProducersGens)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 Exception t = null;
                 foreach (long? gen in dvProducersGens)
@@ -125,6 +137,10 @@ namespace Lucene.Net.Index
                     IOUtils.ReThrow(t);
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
     }
 }
\ No newline at end of file
diff --git a/src/Lucene.Net/Index/SerialMergeScheduler.cs b/src/Lucene.Net/Index/SerialMergeScheduler.cs
index fcfa922..87a2f7b 100644
--- a/src/Lucene.Net/Index/SerialMergeScheduler.cs
+++ b/src/Lucene.Net/Index/SerialMergeScheduler.cs
@@ -1,3 +1,4 @@
+using Lucene.Net.Support.Threading;
 using System.Runtime.CompilerServices;
 
 namespace Lucene.Net.Index
@@ -39,7 +40,8 @@ namespace Lucene.Net.Index
         [MethodImpl(MethodImplOptions.NoInlining)]
         public override void Merge(IndexWriter writer, MergeTrigger trigger, bool newMergesFound) // LUCENENET NOTE: This was internal in the original, but the base class is public so there isn't much choice here
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 while (true)
                 {
@@ -51,6 +53,10 @@ namespace Lucene.Net.Index
                     writer.Merge(merge);
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         protected override void Dispose(bool disposing)
diff --git a/src/Lucene.Net/Index/SlowCompositeReaderWrapper.cs b/src/Lucene.Net/Index/SlowCompositeReaderWrapper.cs
index 887030c..59812d3 100644
--- a/src/Lucene.Net/Index/SlowCompositeReaderWrapper.cs
+++ b/src/Lucene.Net/Index/SlowCompositeReaderWrapper.cs
@@ -1,4 +1,5 @@
-using Lucene.Net.Diagnostics;
+using Lucene.Net.Diagnostics;
+using Lucene.Net.Support.Threading;
 using System.Collections.Generic;
 
 namespace Lucene.Net.Index
@@ -109,7 +110,8 @@ namespace Lucene.Net.Index
         {
             EnsureOpen();
             OrdinalMap map = null;
-            lock (cachedOrdMaps)
+            UninterruptableMonitor.Enter(cachedOrdMaps);
+            try
             {
                 if (!cachedOrdMaps.TryGetValue(field, out map))
                 {
@@ -126,6 +128,10 @@ namespace Lucene.Net.Index
                     return dv;
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(cachedOrdMaps);
+            }
             // cached ordinal map
             if (FieldInfos.FieldInfo(field).DocValuesType != DocValuesType.SORTED)
             {
@@ -149,7 +155,8 @@ namespace Lucene.Net.Index
         {
             EnsureOpen();
             OrdinalMap map = null;
-            lock (cachedOrdMaps)
+            UninterruptableMonitor.Enter(cachedOrdMaps);
+            try
             {
                 if (!cachedOrdMaps.TryGetValue(field, out map))
                 {
@@ -166,6 +173,10 @@ namespace Lucene.Net.Index
                     return dv;
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(cachedOrdMaps);
+            }
             // cached ordinal map
             if (FieldInfos.FieldInfo(field).DocValuesType != DocValuesType.SORTED_SET)
             {
diff --git a/src/Lucene.Net/Index/SnapshotDeletionPolicy.cs b/src/Lucene.Net/Index/SnapshotDeletionPolicy.cs
index 44c92e9..1ead843 100644
--- a/src/Lucene.Net/Index/SnapshotDeletionPolicy.cs
+++ b/src/Lucene.Net/Index/SnapshotDeletionPolicy.cs
@@ -1,4 +1,5 @@
 using Lucene.Net.Diagnostics;
+using Lucene.Net.Support.Threading;
 using System;
 using System.Collections.Generic;
 
@@ -75,16 +76,22 @@ namespace Lucene.Net.Index
 
         public override void OnCommit<T>(IList<T> commits)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 primary.OnCommit(WrapCommits(commits));
                 m_lastCommit = commits[commits.Count - 1];
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         public override void OnInit<T>(IList<T> commits)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 initCalled = true;
                 primary.OnInit(WrapCommits(commits));
@@ -100,6 +107,10 @@ namespace Lucene.Net.Index
                     m_lastCommit = commits[commits.Count - 1];
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -109,11 +120,16 @@ namespace Lucene.Net.Index
         ///          the commit previously returned by <see cref="Snapshot()"/> </param>
         public virtual void Release(IndexCommit commit)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 long gen = commit.Generation;
                 ReleaseGen(gen);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -147,7 +163,8 @@ namespace Lucene.Net.Index
         /// Increments the refCount for this <see cref="IndexCommit"/>. </summary>
         protected internal virtual void IncRef(IndexCommit ic)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 long gen = ic.Generation;
                 int refCountInt;
@@ -162,6 +179,10 @@ namespace Lucene.Net.Index
                 }
                 m_refCounts[gen] = refCountInt + 1;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -182,7 +203,8 @@ namespace Lucene.Net.Index
         /// <returns> the <see cref="IndexCommit"/> that was snapshotted. </returns>
         public virtual IndexCommit Snapshot()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (!initCalled)
                 {
@@ -198,16 +220,25 @@ namespace Lucene.Net.Index
 
                 return m_lastCommit;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
         /// Returns all <see cref="IndexCommit"/>s held by at least one snapshot. </summary>
         public virtual IList<IndexCommit> GetSnapshots()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 return new List<IndexCommit>(m_indexCommits.Values);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -216,7 +247,8 @@ namespace Lucene.Net.Index
         {
             get
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     int total = 0;
                     foreach (var refCount in m_refCounts.Values)
@@ -226,6 +258,10 @@ namespace Lucene.Net.Index
 
                     return total;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
@@ -236,15 +272,21 @@ namespace Lucene.Net.Index
         /// </summary>
         public virtual IndexCommit GetIndexCommit(long gen)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 return m_indexCommits[gen];
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         public override object Clone()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 SnapshotDeletionPolicy other = (SnapshotDeletionPolicy)base.Clone();
                 other.primary = (IndexDeletionPolicy)this.primary.Clone();
@@ -253,6 +295,10 @@ namespace Lucene.Net.Index
                 other.m_indexCommits = new Dictionary<long?, IndexCommit>(m_indexCommits);
                 return other;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -299,7 +345,8 @@ namespace Lucene.Net.Index
 
             public override void Delete()
             {
-                lock (outerInstance)
+                UninterruptableMonitor.Enter(outerInstance);
+                try
                 {
                     // Suppress the delete request if this commit point is
                     // currently snapshotted.
@@ -308,6 +355,10 @@ namespace Lucene.Net.Index
                         m_cp.Delete();
                     }
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(outerInstance);
+                }
             }
 
             public override Directory Directory => m_cp.Directory;
diff --git a/src/Lucene.Net/Index/StoredFieldsProcessor.cs b/src/Lucene.Net/Index/StoredFieldsProcessor.cs
index 4cbb401..342562b 100644
--- a/src/Lucene.Net/Index/StoredFieldsProcessor.cs
+++ b/src/Lucene.Net/Index/StoredFieldsProcessor.cs
@@ -1,5 +1,6 @@
-using Lucene.Net.Diagnostics;
+using Lucene.Net.Diagnostics;
 using Lucene.Net.Support;
+using Lucene.Net.Support.Threading;
 using System;
 using System.Runtime.CompilerServices;
 
@@ -99,7 +100,8 @@ namespace Lucene.Net.Index
 
         private void InitFieldsWriter(IOContext context)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (fieldsWriter == null)
                 {
@@ -107,6 +109,10 @@ namespace Lucene.Net.Index
                     lastDocID = 0;
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         [MethodImpl(MethodImplOptions.NoInlining)]
diff --git a/src/Lucene.Net/Index/TermsEnum.cs b/src/Lucene.Net/Index/TermsEnum.cs
index c185b93..bb760e1 100644
--- a/src/Lucene.Net/Index/TermsEnum.cs
+++ b/src/Lucene.Net/Index/TermsEnum.cs
@@ -1,4 +1,5 @@
-using Lucene.Net.Util;
+using Lucene.Net.Support.Threading;
+using Lucene.Net.Util;
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -336,10 +337,15 @@ namespace Lucene.Net.Index
             {
                 get
                 {
-                    lock (this)
+                    UninterruptableMonitor.Enter(this);
+                    try
                     {
                         return base.Attributes;
                     }
+                    finally
+                    {
+                        UninterruptableMonitor.Exit(this);
+                    }
                 }
             }
 
diff --git a/src/Lucene.Net/Search/CachingWrapperFilter.cs b/src/Lucene.Net/Search/CachingWrapperFilter.cs
index 22600eb..1c170b5 100644
--- a/src/Lucene.Net/Search/CachingWrapperFilter.cs
+++ b/src/Lucene.Net/Search/CachingWrapperFilter.cs
@@ -1,5 +1,6 @@
-using Lucene.Net.Diagnostics;
+using Lucene.Net.Diagnostics;
 using Lucene.Net.Support;
+using Lucene.Net.Support.Threading;
 using System.Collections.Generic;
 using System.Runtime.CompilerServices;
 
@@ -171,7 +172,8 @@ namespace Lucene.Net.Search
         {
             // Sync only to pull the current set of values:
             List<DocIdSet> docIdSets;
-            lock (_cache)
+            UninterruptableMonitor.Enter(_cache);
+            try
             {
 #if FEATURE_CONDITIONALWEAKTABLE_ENUMERATOR
                 docIdSets = new List<DocIdSet>();
@@ -181,6 +183,10 @@ namespace Lucene.Net.Search
                 docIdSets = new List<DocIdSet>(_cache.Values);
 #endif
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(_cache);
+            }
 
             long total = 0;
             foreach (DocIdSet dis in docIdSets)
diff --git a/src/Lucene.Net/Search/ControlledRealTimeReopenThread.cs b/src/Lucene.Net/Search/ControlledRealTimeReopenThread.cs
index 954c018..b1f8020 100644
--- a/src/Lucene.Net/Search/ControlledRealTimeReopenThread.cs
+++ b/src/Lucene.Net/Search/ControlledRealTimeReopenThread.cs
@@ -1,5 +1,6 @@
 using J2N;
 using J2N.Threading;
+using Lucene.Net.Support.Threading;
 using System;
 using System.Threading;
 
@@ -103,12 +104,17 @@ namespace Lucene.Net.Search
 
         private void RefreshDone()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 // if we're finishing, , make it out so that all waiting search threads will return
                 searchingGen = finish ? long.MaxValue : refreshStartGen;
                 available.Set();
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
             reopenCond.Reset();
         }
 
@@ -192,7 +198,9 @@ namespace Lucene.Net.Search
             {
                 throw new ArgumentException("targetGen=" + targetGen + " was never returned by the ReferenceManager instance (current gen=" + curGen + ")");
             }
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
+            {
                 if (targetGen <= searchingGen)
                     return true;
                 else
@@ -201,6 +209,11 @@ namespace Lucene.Net.Search
                     reopenCond.Set();
                     available.Reset();
                 }
+            }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
 
             long startMS = Time.NanoTime() / 1000000;
 
@@ -239,8 +252,15 @@ namespace Lucene.Net.Search
             {
                 bool hasWaiting;
 
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
+                {
                     hasWaiting = waitingGen > searchingGen;
+                }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
 
                 long nextReopenStartNS = lastReopenStartNS + (hasWaiting ? targetMinStaleNS : targetMaxStaleNS);
                 long sleepNS = nextReopenStartNS - Time.NanoTime();
diff --git a/src/Lucene.Net/Search/FieldCacheImpl.cs b/src/Lucene.Net/Search/FieldCacheImpl.cs
index 8a64830..15069f1 100644
--- a/src/Lucene.Net/Search/FieldCacheImpl.cs
+++ b/src/Lucene.Net/Search/FieldCacheImpl.cs
@@ -3,6 +3,7 @@ using Lucene.Net.Diagnostics;
 using Lucene.Net.Index;
 using Lucene.Net.Support;
 using Lucene.Net.Support.IO;
+using Lucene.Net.Support.Threading;
 using System;
 using System.Collections.Generic;
 using System.IO;
@@ -96,15 +97,21 @@ namespace Lucene.Net.Search
 
         public virtual void PurgeAllCaches()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 Init();
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         public virtual void PurgeByCacheKey(object coreCacheKey)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 // LUCENENET specific - removed unnecessary Dictionary and loop
                 caches_typeof_sbyte.PurgeByCacheKey(coreCacheKey);
@@ -118,13 +125,18 @@ namespace Lucene.Net.Search
                 caches_typeof_DocTermOrds.PurgeByCacheKey(coreCacheKey);
                 caches_typeof_DocsWithFieldCache.PurgeByCacheKey(coreCacheKey);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         public virtual FieldCache.CacheEntry[] GetCacheEntries()
         {
             // LUCENENET specific - instantiate/ToArray() outside of lock to improve performance
             IList<FieldCache.CacheEntry> result = new List<FieldCache.CacheEntry>(17);
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 // LUCENENET specific - refactored to use generic CacheKey to reduce casting and removed unnecessary Dictionary/loop
                 AddCacheEntries(result, typeof(sbyte), caches_typeof_sbyte);
@@ -138,12 +150,17 @@ namespace Lucene.Net.Search
                 AddCacheEntries(result, typeof(DocTermOrds), caches_typeof_DocTermOrds);
                 AddCacheEntries(result, typeof(DocsWithFieldCache), caches_typeof_DocsWithFieldCache);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
             return result.ToArray();
         }
 
         private void AddCacheEntries<TKey, TValue>(IList<FieldCache.CacheEntry> result, Type cacheType, Cache<TKey, TValue> cache) where TKey : CacheKey
         {
-            lock (cache.readerCache)
+            UninterruptableMonitor.Enter(cache.readerCache);
+            try
             {
                 foreach (var readerCacheEntry in cache.readerCache)
                 {
@@ -160,6 +177,10 @@ namespace Lucene.Net.Search
                     }
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(cache.readerCache);
+            }
         }
 
         // per-segment fieldcaches don't purge until the shared core closes.
@@ -245,8 +266,15 @@ namespace Lucene.Net.Search
             /// Remove this reader from the cache, if present. </summary>
             public virtual void PurgeByCacheKey(object coreCacheKey)
             {
-                lock (readerCache)
+                UninterruptableMonitor.Enter(readerCache);
+                try
+                {
                     readerCache.Remove(coreCacheKey);
+                }
+                finally
+                {
+                    UninterruptableMonitor.Exit(readerCache);
+                }
             }
 
             /// <summary>
@@ -257,7 +285,8 @@ namespace Lucene.Net.Search
             {
                 IDictionary<TKey, object> innerCache;
                 object readerKey = reader.CoreCacheKey;
-                lock (readerCache)
+                UninterruptableMonitor.Enter(readerCache);
+                try
                 {
 #if FEATURE_CONDITIONALWEAKTABLE_ENUMERATOR
 
@@ -286,6 +315,10 @@ namespace Lucene.Net.Search
                         innerCache[key] = value;
                     // else if another thread beat us to it, leave the current value
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(readerCache);
+                }
             }
 
             public virtual TValue Get(AtomicReader reader, TKey key, bool setDocsWithField)
@@ -293,7 +326,8 @@ namespace Lucene.Net.Search
                 IDictionary<TKey, object> innerCache;
                 object value = null;
                 object readerKey = reader.CoreCacheKey;
-                lock (readerCache)
+                UninterruptableMonitor.Enter(readerCache);
+                try
                 {
 #if FEATURE_CONDITIONALWEAKTABLE_ENUMERATOR
                     innerCache = readerCache.GetValue(readerKey, (readerKey) =>
@@ -327,17 +361,27 @@ namespace Lucene.Net.Search
                             innerCache[key] = value = new FieldCache.CreationPlaceholder<TValue>();
                     }
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(readerCache);
+                }
                 if (value is FieldCache.CreationPlaceholder<TValue> progress)
                 {
-                    lock (value)
+                    UninterruptableMonitor.Enter(value);
+                    try
                     {
                         if (progress.Value is null)
                         {
                             progress.Value = CreateValue(reader, key, setDocsWithField);
-                            lock (readerCache)
+                            UninterruptableMonitor.Enter(readerCache);
+                            try
                             {
                                 innerCache[key] = progress.Value;
                             }
+                            finally
+                            {
+                                UninterruptableMonitor.Exit(readerCache);
+                            }
                             // Only check if key.custom (the parser) is
                             // non-null; else, we check twice for a single
                             // call to FieldCache.getXXX
@@ -352,6 +396,10 @@ namespace Lucene.Net.Search
                         }
                         return progress.Value;
                     }
+                    finally
+                    {
+                        UninterruptableMonitor.Exit(value);
+                    }
                 }
                 return (TValue)value;
             }
diff --git a/src/Lucene.Net/Search/ReferenceManager.cs b/src/Lucene.Net/Search/ReferenceManager.cs
index 37bd91e..c6f66df 100644
--- a/src/Lucene.Net/Search/ReferenceManager.cs
+++ b/src/Lucene.Net/Search/ReferenceManager.cs
@@ -68,13 +68,18 @@ namespace Lucene.Net.Search
 
         private void SwapReference(G newReference)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 EnsureOpen();
                 G oldReference = current;
                 current = newReference;
                 Release(oldReference);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -173,7 +178,8 @@ namespace Lucene.Net.Search
         {
             if (disposing)
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     if (current != null)
                     {
@@ -183,6 +189,10 @@ namespace Lucene.Net.Search
                         SwapReference(null);
                     }
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
diff --git a/src/Lucene.Net/Search/SearcherLifetimeManager.cs b/src/Lucene.Net/Search/SearcherLifetimeManager.cs
index a62eb41..36348a5 100644
--- a/src/Lucene.Net/Search/SearcherLifetimeManager.cs
+++ b/src/Lucene.Net/Search/SearcherLifetimeManager.cs
@@ -1,4 +1,5 @@
 using J2N;
+using Lucene.Net.Support.Threading;
 using System;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
@@ -127,10 +128,15 @@ namespace Lucene.Net.Search
 
             public void Dispose()
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     Searcher.IndexReader.DecRef();
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
@@ -264,7 +270,8 @@ namespace Lucene.Net.Search
         /// </summary>
         public virtual void Prune(IPruner pruner)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 // Cannot just pass searchers.values() to ArrayList ctor
                 // (not thread-safe since the values can change while
@@ -299,6 +306,10 @@ namespace Lucene.Net.Search
                     lastRecordTimeSec = tracker.RecordTimeSec;
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -330,7 +341,8 @@ namespace Lucene.Net.Search
         {
             if (disposing)
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     _closed = true;
                     IList<SearcherTracker> toClose = new List<SearcherTracker>(_searchers.Values.Select(item => item.Value));
@@ -350,6 +362,10 @@ namespace Lucene.Net.Search
                         throw IllegalStateException.Create("another thread called record while this SearcherLifetimeManager instance was being disposed; not all searchers were disposed");
                     }
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
     }
diff --git a/src/Lucene.Net/Search/TimeLimitingCollector.cs b/src/Lucene.Net/Search/TimeLimitingCollector.cs
index 4549503..23477cd 100644
--- a/src/Lucene.Net/Search/TimeLimitingCollector.cs
+++ b/src/Lucene.Net/Search/TimeLimitingCollector.cs
@@ -1,4 +1,5 @@
 using J2N.Threading;
+using Lucene.Net.Support.Threading;
 using System;
 #if FEATURE_SERIALIZABLE_EXCEPTIONS
 using System.Runtime.Serialization;
diff --git a/src/Lucene.Net/Store/CompoundFileDirectory.cs b/src/Lucene.Net/Store/CompoundFileDirectory.cs
index 5765045..92dca31 100644
--- a/src/Lucene.Net/Store/CompoundFileDirectory.cs
+++ b/src/Lucene.Net/Store/CompoundFileDirectory.cs
@@ -2,6 +2,7 @@
 using J2N.Numerics;
 using Lucene.Net.Diagnostics;
 using Lucene.Net.Support;
+using Lucene.Net.Support.Threading;
 using System;
 using System.Collections.Generic;
 using System.IO;
@@ -285,7 +286,8 @@ namespace Lucene.Net.Store
 
         protected override void Dispose(bool disposing)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (disposing)
                 {
@@ -306,11 +308,16 @@ namespace Lucene.Net.Store
                     }
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         public override IndexInput OpenInput(string name, IOContext context)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 EnsureOpen();
                 if (Debugging.AssertsEnabled) Debugging.Assert(!openForWrite);
@@ -323,6 +330,10 @@ namespace Lucene.Net.Store
                 }
                 return handle.OpenSlice(name, entry.Offset, entry.Length);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
diff --git a/src/Lucene.Net/Store/CompoundFileWriter.cs b/src/Lucene.Net/Store/CompoundFileWriter.cs
index 583d9d2..63f01f9 100644
--- a/src/Lucene.Net/Store/CompoundFileWriter.cs
+++ b/src/Lucene.Net/Store/CompoundFileWriter.cs
@@ -1,6 +1,7 @@
 using J2N.Collections.Generic.Extensions;
 using J2N.Threading.Atomic;
 using Lucene.Net.Diagnostics;
+using Lucene.Net.Support.Threading;
 using System;
 using System.Collections.Generic;
 using System.IO;
@@ -100,7 +101,8 @@ namespace Lucene.Net.Store
 
         private IndexOutput GetOutput()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (dataOut == null)
                 {
@@ -121,6 +123,10 @@ namespace Lucene.Net.Store
                 }
                 return dataOut;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
diff --git a/src/Lucene.Net/Store/Lock.cs b/src/Lucene.Net/Store/Lock.cs
index 0f9d167..5613439 100644
--- a/src/Lucene.Net/Store/Lock.cs
+++ b/src/Lucene.Net/Store/Lock.cs
@@ -1,4 +1,5 @@
-using System;
+using Lucene.Net.Support.Threading;
+using System;
 using System.IO;
 using System.Threading;
 
diff --git a/src/Lucene.Net/Store/LockVerifyServer.cs b/src/Lucene.Net/Store/LockVerifyServer.cs
index edfa6f0..af4c47c 100644
--- a/src/Lucene.Net/Store/LockVerifyServer.cs
+++ b/src/Lucene.Net/Store/LockVerifyServer.cs
@@ -1,4 +1,5 @@
 using J2N.Threading;
+using Lucene.Net.Support.Threading;
 using Lucene.Net.Util;
 using System;
 using System.Globalization;
@@ -136,7 +137,8 @@ namespace Lucene.Net.Store
                             return; // closed
                         }
 
-                        lock (localLock)
+                        UninterruptableMonitor.Enter(localLock);
+                        try
                         {
                             int currentLock = lockedID[0];
                             if (currentLock == -2)
@@ -171,6 +173,10 @@ namespace Lucene.Net.Store
                             intWriter.Write((byte)command);
                             stream.Flush();
                         }
+                        finally
+                        {
+                            UninterruptableMonitor.Exit(localLock);
+                        }
                     }
                 }
                 catch (Exception e) when (e.IsRuntimeException() || e.IsError())
diff --git a/src/Lucene.Net/Store/NRTCachingDirectory.cs b/src/Lucene.Net/Store/NRTCachingDirectory.cs
index ba50abf..94e9c5f 100644
--- a/src/Lucene.Net/Store/NRTCachingDirectory.cs
+++ b/src/Lucene.Net/Store/NRTCachingDirectory.cs
@@ -1,4 +1,5 @@
 using J2N.Collections.Generic.Extensions;
+using Lucene.Net.Support.Threading;
 using System;
 using System.Collections.Generic;
 using System.IO;
@@ -120,7 +121,8 @@ namespace Lucene.Net.Store
 
         public override string[] ListAll()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 ISet<string> files = new JCG.HashSet<string>();
                 foreach (string f in cache.ListAll())
@@ -152,6 +154,10 @@ namespace Lucene.Net.Store
                 }
                 return files.ToArray();
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -166,15 +172,21 @@ namespace Lucene.Net.Store
         [Obsolete("this method will be removed in 5.0")]
         public override bool FileExists(string name)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 return cache.FileExists(name) || @delegate.FileExists(name);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         public override void DeleteFile(string name)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (VERBOSE)
                 {
@@ -191,11 +203,16 @@ namespace Lucene.Net.Store
                     @delegate.DeleteFile(name);
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         public override long FileLength(string name)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
 #pragma warning disable 612, 618
                 if (cache.FileExists(name))
@@ -208,6 +225,10 @@ namespace Lucene.Net.Store
                     return @delegate.FileLength(name);
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         public virtual string[] ListCachedFiles()
@@ -266,7 +287,8 @@ namespace Lucene.Net.Store
 
         public override IndexInput OpenInput(string name, IOContext context)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 if (VERBOSE)
                 {
@@ -287,11 +309,16 @@ namespace Lucene.Net.Store
                     return @delegate.OpenInput(name, context);
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         public override IndexInputSlicer CreateSlicer(string name, IOContext context)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 EnsureOpen();
                 if (VERBOSE)
@@ -313,6 +340,10 @@ namespace Lucene.Net.Store
                     return @delegate.CreateSlicer(name, context);
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         /// <summary>
@@ -364,7 +395,8 @@ namespace Lucene.Net.Store
         {
             // Only let one thread uncache at a time; this only
             // happens during commit() or close():
-            lock (uncacheLock)
+            UninterruptableMonitor.Enter(uncacheLock);
+            try
             {
                 if (VERBOSE)
                 {
@@ -391,12 +423,21 @@ namespace Lucene.Net.Store
                 }
 
                 // Lock order: uncacheLock -> this
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     // Must sync here because other sync methods have
                     // if (cache.fileExists(name)) { ... } else { ... }:
                     cache.DeleteFile(fileName);
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
+            }
+            finally
+            {
+                UninterruptableMonitor.Exit(uncacheLock);
             }
         }
     }
diff --git a/src/Lucene.Net/Store/NativeFSLockFactory.cs b/src/Lucene.Net/Store/NativeFSLockFactory.cs
index 484d889..374deee 100644
--- a/src/Lucene.Net/Store/NativeFSLockFactory.cs
+++ b/src/Lucene.Net/Store/NativeFSLockFactory.cs
@@ -3,6 +3,7 @@ using Lucene.Net.Util;
 using System;
 using System.IO;
 using System.Collections.Generic;
+using Lucene.Net.Support.Threading;
 
 namespace Lucene.Net.Store
 {
@@ -197,9 +198,16 @@ namespace Lucene.Net.Store
         {
             var path = GetCanonicalPathOfLockFile(lockName);
             Lock l;
-            lock (_locks)
+            UninterruptableMonitor.Enter(_locks);
+            try
+            {
                 if (!_locks.TryGetValue(path, out l))
                     _locks.Add(path, l = NewLock(path));
+            }
+            finally
+            {
+                UninterruptableMonitor.Exit(_locks);
+            }
             return l;
         }
 
@@ -225,12 +233,19 @@ namespace Lucene.Net.Store
             var path = GetCanonicalPathOfLockFile(lockName);
             // this is the reason why we can't use ConcurrentDictionary: we need the removal and disposal of the lock to be atomic
             // otherwise it may clash with MakeLock making a lock and ClearLock disposing of it in another thread.
-            lock (_locks)
+            UninterruptableMonitor.Enter(_locks);
+            try
+            {
                 if (_locks.TryGetValue(path, out Lock l))
                 {
                     _locks.Remove(path);
                     l.Dispose();
                 }
+            }
+            finally
+            {
+                UninterruptableMonitor.Exit(_locks);
+            }
         }
     }
 
@@ -259,7 +274,8 @@ namespace Lucene.Net.Store
 
         public override bool Obtain()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 FailureReason = null;
 
@@ -317,20 +333,32 @@ namespace Lucene.Net.Store
 
                 return channel != null;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         protected override void Dispose(bool disposing)
         {
             if (disposing)
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     // whether or not we have created a file, we need to remove
                     // the lock instance from the dictionary that tracks them.
                     try
                     {
-                        lock (NativeFSLockFactory._locks)
+                        UninterruptableMonitor.Enter(NativeFSLockFactory._locks);
+                        try
+                        {
                             NativeFSLockFactory._locks.Remove(path);
+                        }
+                        finally
+                        {
+                            UninterruptableMonitor.Exit(NativeFSLockFactory._locks);
+                        }
                     }
                     finally
                     {
@@ -361,12 +389,17 @@ namespace Lucene.Net.Store
                         }
                     }
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
         public override bool IsLocked()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 // The test for is isLocked is not directly possible with native file locks:
 
@@ -400,6 +433,10 @@ namespace Lucene.Net.Store
                     return false;
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         public override string ToString()
@@ -465,7 +502,8 @@ namespace Lucene.Net.Store
 
         public override bool Obtain()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 FailureReason = null;
 
@@ -497,20 +535,32 @@ namespace Lucene.Net.Store
                 }
                 return channel != null;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         protected override void Dispose(bool disposing)
         {
             if (disposing)
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     // whether or not we have created a file, we need to remove
                     // the lock instance from the dictionary that tracks them.
                     try
                     {
-                        lock (NativeFSLockFactory._locks)
+                        UninterruptableMonitor.Enter(NativeFSLockFactory._locks);
+                        try
+                        {
                             NativeFSLockFactory._locks.Remove(path);
+                        }
+                        finally
+                        {
+                            UninterruptableMonitor.Exit(NativeFSLockFactory._locks);
+                        }
                     }
                     finally
                     {
@@ -527,12 +577,17 @@ namespace Lucene.Net.Store
                         }
                     }
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
         public override bool IsLocked()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 // First a shortcut, if a lock reference in this instance is available
                 if (channel != null)
@@ -557,6 +612,10 @@ namespace Lucene.Net.Store
                     return false;
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         public override string ToString()
@@ -617,7 +676,8 @@ namespace Lucene.Net.Store
 
         public override bool Obtain()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 FailureReason = null;
 
@@ -662,20 +722,32 @@ namespace Lucene.Net.Store
                 }
                 return channel != null;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         protected override void Dispose(bool disposing)
         {
             if (disposing)
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     // whether or not we have created a file, we need to remove
                     // the lock instance from the dictionary that tracks them.
                     try
                     {
-                        lock (NativeFSLockFactory._locks)
+                        UninterruptableMonitor.Enter(NativeFSLockFactory._locks);
+                        try
+                        {
                             NativeFSLockFactory._locks.Remove(path);
+                        }
+                        finally
+                        {
+                            UninterruptableMonitor.Exit(NativeFSLockFactory._locks);
+                        }
                     }
                     finally
                     {
@@ -700,12 +772,17 @@ namespace Lucene.Net.Store
                         }
                     }
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
         public override bool IsLocked()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 // First a shortcut, if a lock reference in this instance is available
                 if (channel != null)
@@ -734,6 +811,10 @@ namespace Lucene.Net.Store
                     return false;
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         public override string ToString()
diff --git a/src/Lucene.Net/Store/RAMFile.cs b/src/Lucene.Net/Store/RAMFile.cs
index 1da3b5e..80d3bb9 100644
--- a/src/Lucene.Net/Store/RAMFile.cs
+++ b/src/Lucene.Net/Store/RAMFile.cs
@@ -1,3 +1,4 @@
+using Lucene.Net.Support.Threading;
 using System.Collections.Generic;
 
 namespace Lucene.Net.Store
@@ -50,28 +51,43 @@ namespace Lucene.Net.Store
         {
             get
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     return length;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
             set
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     this.length = value;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
         protected internal byte[] AddBuffer(int size)
         {
             byte[] buffer = NewBuffer(size);
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 m_buffers.Add(buffer);
                 m_sizeInBytes += size;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
 
             if (directory != null)
             {
@@ -82,20 +98,30 @@ namespace Lucene.Net.Store
 
         protected internal byte[] GetBuffer(int index)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 return m_buffers[index];
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         protected internal int NumBuffers
         {
             get
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     return m_buffers.Count;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
         }
 
@@ -111,10 +137,15 @@ namespace Lucene.Net.Store
 
         public virtual long GetSizeInBytes()
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 return m_sizeInBytes;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
     }
 }
\ No newline at end of file
diff --git a/src/Lucene.Net/Store/RateLimiter.cs b/src/Lucene.Net/Store/RateLimiter.cs
index 61e2339..9e97211 100644
--- a/src/Lucene.Net/Store/RateLimiter.cs
+++ b/src/Lucene.Net/Store/RateLimiter.cs
@@ -1,4 +1,5 @@
 using J2N;
+using Lucene.Net.Support.Threading;
 using System;
 using System.Threading;
 
diff --git a/src/Lucene.Net/Store/SimpleFSDirectory.cs b/src/Lucene.Net/Store/SimpleFSDirectory.cs
index e0a6e2e..8247314 100644
--- a/src/Lucene.Net/Store/SimpleFSDirectory.cs
+++ b/src/Lucene.Net/Store/SimpleFSDirectory.cs
@@ -1,4 +1,5 @@
 using Lucene.Net.Diagnostics;
+using Lucene.Net.Support.Threading;
 using System;
 using System.IO;
 
@@ -205,7 +206,8 @@ namespace Lucene.Net.Store
             /// <see cref="IndexInput"/> methods </summary>
             protected override void ReadInternal(byte[] b, int offset, int len)
             {
-                lock (m_file)
+                UninterruptableMonitor.Enter(m_file);
+                try
                 {
                     long position = m_off + Position; // LUCENENET specific: Renamed from getFilePointer() to match FileStream
                     m_file.Seek(position, SeekOrigin.Begin);
@@ -242,6 +244,10 @@ namespace Lucene.Net.Store
                         throw new IOException(ioe.Message + ": " + this, ioe);
                     }
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(m_file);
+                }
             }
 
             protected override void SeekInternal(long position)
diff --git a/src/Lucene.Net/Store/SingleInstanceLockFactory.cs b/src/Lucene.Net/Store/SingleInstanceLockFactory.cs
index e432340..f78bc0b 100644
--- a/src/Lucene.Net/Store/SingleInstanceLockFactory.cs
+++ b/src/Lucene.Net/Store/SingleInstanceLockFactory.cs
@@ -1,3 +1,4 @@
+using Lucene.Net.Support.Threading;
 using System.Collections.Generic;
 using JCG = J2N.Collections.Generic;
 
@@ -43,13 +44,18 @@ namespace Lucene.Net.Store
 
         public override void ClearLock(string lockName)
         {
-            lock (locks)
+            UninterruptableMonitor.Enter(locks);
+            try
             {
                 if (locks.Contains(lockName))
                 {
                     locks.Remove(lockName);
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(locks);
+            }
         }
     }
 
@@ -66,29 +72,44 @@ namespace Lucene.Net.Store
 
         public override bool Obtain()
         {
-            lock (locks)
+            UninterruptableMonitor.Enter(locks);
+            try
             {
                 return locks.Add(lockName);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(locks);
+            }
         }
 
         protected override void Dispose(bool disposing)
         {
             if (disposing)
             {
-                lock (locks)
+                UninterruptableMonitor.Enter(locks);
+                try
                 {
                     locks.Remove(lockName);
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(locks);
+                }
             }
         }
 
         public override bool IsLocked()
         {
-            lock (locks)
+            UninterruptableMonitor.Enter(locks);
+            try
             {
                 return locks.Contains(lockName);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(locks);
+            }
         }
 
         public override string ToString()
diff --git a/src/Lucene.Net/Store/VerifyingLockFactory.cs b/src/Lucene.Net/Store/VerifyingLockFactory.cs
index bf9b71b..eff9f59 100644
--- a/src/Lucene.Net/Store/VerifyingLockFactory.cs
+++ b/src/Lucene.Net/Store/VerifyingLockFactory.cs
@@ -1,3 +1,4 @@
+using Lucene.Net.Support.Threading;
 using System;
 using System.IO;
 
@@ -66,7 +67,8 @@ namespace Lucene.Net.Store
 
             public override bool Obtain()
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     bool obtained = @lock.Obtain();
                     if (obtained)
@@ -75,21 +77,31 @@ namespace Lucene.Net.Store
                     }
                     return obtained;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
 
             public override bool IsLocked()
             {
-                lock (this)
+                UninterruptableMonitor.Enter(this);
+                try
                 {
                     return @lock.IsLocked();
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(this);
+                }
             }
 
             protected override void Dispose(bool disposing)
             {
                 if (disposing)
                 {
-                    lock (this)
+                    UninterruptableMonitor.Enter(this);
+                    try
                     {
                         if (IsLocked())
                         {
@@ -97,6 +109,10 @@ namespace Lucene.Net.Store
                             @lock.Dispose();
                         }
                     }
+                    finally
+                    {
+                        UninterruptableMonitor.Exit(this);
+                    }
                 }
             }
         }
@@ -114,18 +130,28 @@ namespace Lucene.Net.Store
 
         public override Lock MakeLock(string lockName)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 return new CheckedLock(this, lf.MakeLock(lockName));
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
 
         public override void ClearLock(string lockName)
         {
-            lock (this)
+            UninterruptableMonitor.Enter(this);
+            try
             {
                 lf.ClearLock(lockName);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(this);
+            }
         }
     }
 }
\ No newline at end of file
diff --git a/src/Lucene.Net/Support/Codecs/DefaultCodecFactory.cs b/src/Lucene.Net/Support/Codecs/DefaultCodecFactory.cs
index c4e74a0..c1e66e7 100644
--- a/src/Lucene.Net/Support/Codecs/DefaultCodecFactory.cs
+++ b/src/Lucene.Net/Support/Codecs/DefaultCodecFactory.cs
@@ -1,4 +1,5 @@
-using Lucene.Net.Util;
+using Lucene.Net.Support.Threading;
+using Lucene.Net.Util;
 using System;
 using System.Collections.Generic;
 using System.Reflection;
@@ -218,10 +219,15 @@ namespace Lucene.Net.Codecs
         private void PutCodecTypeImpl(Type codec)
         {
             string name = GetServiceName(codec);
-            lock (m_initializationLock)
+            UninterruptableMonitor.Enter(m_initializationLock);
+            try
             {
                 codecNameToTypeMap[name] = codec;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(m_initializationLock);
+            }
         }
 
         /// <summary>
@@ -232,11 +238,16 @@ namespace Lucene.Net.Codecs
         public virtual Codec GetCodec(string name)
         {
             EnsureInitialized(); // Safety in case a subclass doesn't call it
-            lock (m_initializationLock)
+            UninterruptableMonitor.Enter(m_initializationLock);
+            try
             {
                 Type codecType = GetCodecType(name);
                 return GetCodec(codecType);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(m_initializationLock);
+            }
         }
 
         /// <summary>
@@ -250,7 +261,8 @@ namespace Lucene.Net.Codecs
                 throw new ArgumentNullException(nameof(type));
             if (!codecInstanceCache.TryGetValue(type, out Codec instance))
             {
-                lock (m_initializationLock)
+                UninterruptableMonitor.Enter(m_initializationLock);
+                try
                 {
                     if (!codecInstanceCache.TryGetValue(type, out instance))
                     {
@@ -258,6 +270,10 @@ namespace Lucene.Net.Codecs
                         codecInstanceCache[type] = instance;
                     }
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(m_initializationLock);
+                }
             }
 
             return instance;
diff --git a/src/Lucene.Net/Support/Codecs/DefaultDocValuesFormatFactory.cs b/src/Lucene.Net/Support/Codecs/DefaultDocValuesFormatFactory.cs
index e7e1b4f..b96becf 100644
--- a/src/Lucene.Net/Support/Codecs/DefaultDocValuesFormatFactory.cs
+++ b/src/Lucene.Net/Support/Codecs/DefaultDocValuesFormatFactory.cs
@@ -1,4 +1,5 @@
-using Lucene.Net.Util;
+using Lucene.Net.Support.Threading;
+using Lucene.Net.Util;
 using System;
 using System.Collections.Generic;
 using System.Reflection;
@@ -214,10 +215,15 @@ namespace Lucene.Net.Codecs
         private void PutDocValuesFormatTypeImpl(Type docValuesFormat)
         {
             string name = GetServiceName(docValuesFormat);
-            lock (m_initializationLock)
+            UninterruptableMonitor.Enter(m_initializationLock);
+            try
             {
                 docValuesFormatNameToTypeMap[name] = docValuesFormat;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(m_initializationLock);
+            }
         }
 
         /// <summary>
@@ -228,11 +234,16 @@ namespace Lucene.Net.Codecs
         public virtual DocValuesFormat GetDocValuesFormat(string name)
         {
             EnsureInitialized(); // Safety in case a subclass doesn't call it
-            lock (m_initializationLock)
+            UninterruptableMonitor.Enter(m_initializationLock);
+            try
             {
                 Type codecType = GetDocValuesFormatType(name);
                 return GetDocValuesFormat(codecType);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(m_initializationLock);
+            }
         }
 
         /// <summary>
@@ -246,7 +257,8 @@ namespace Lucene.Net.Codecs
                 throw new ArgumentNullException(nameof(type));
             if (!docValuesFormatInstanceCache.TryGetValue(type, out DocValuesFormat instance))
             {
-                lock (m_initializationLock)
+                UninterruptableMonitor.Enter(m_initializationLock);
+                try
                 {
                     if (!docValuesFormatInstanceCache.TryGetValue(type, out instance))
                     {
@@ -254,6 +266,10 @@ namespace Lucene.Net.Codecs
                         docValuesFormatInstanceCache[type] = instance;
                     }
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(m_initializationLock);
+                }
             }
 
             return instance;
diff --git a/src/Lucene.Net/Support/Codecs/DefaultPostingsFormatFactory.cs b/src/Lucene.Net/Support/Codecs/DefaultPostingsFormatFactory.cs
index 8da5aeb..40637f2 100644
--- a/src/Lucene.Net/Support/Codecs/DefaultPostingsFormatFactory.cs
+++ b/src/Lucene.Net/Support/Codecs/DefaultPostingsFormatFactory.cs
@@ -1,4 +1,5 @@
-using Lucene.Net.Util;
+using Lucene.Net.Support.Threading;
+using Lucene.Net.Util;
 using System;
 using System.Collections.Generic;
 using System.Reflection;
@@ -214,10 +215,15 @@ namespace Lucene.Net.Codecs
         private void PutPostingsFormatTypeImpl(Type postingsFormat)
         {
             string name = GetServiceName(postingsFormat);
-            lock (m_initializationLock)
+            UninterruptableMonitor.Enter(m_initializationLock);
+            try
             {
                 postingsFormatNameToTypeMap[name] = postingsFormat;
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(m_initializationLock);
+            }
         }
 
         /// <summary>
@@ -228,11 +234,16 @@ namespace Lucene.Net.Codecs
         public virtual PostingsFormat GetPostingsFormat(string name)
         {
             EnsureInitialized(); // Safety in case a subclass doesn't call it
-            lock (m_initializationLock)
+            UninterruptableMonitor.Enter(m_initializationLock);
+            try
             {
                 Type codecType = GetPostingsFormatType(name);
                 return GetPostingsFormat(codecType);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(m_initializationLock);
+            }
         }
 
         /// <summary>
@@ -246,7 +257,8 @@ namespace Lucene.Net.Codecs
                 throw new ArgumentNullException(nameof(type));
             if (!postingsFormatInstanceCache.TryGetValue(type, out PostingsFormat instance))
             {
-                lock (m_initializationLock)
+                UninterruptableMonitor.Enter(m_initializationLock);
+                try
                 {
                     if (!postingsFormatInstanceCache.TryGetValue(type, out instance))
                     {
@@ -254,6 +266,10 @@ namespace Lucene.Net.Codecs
                         postingsFormatInstanceCache[type] = instance;
                     }
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(m_initializationLock);
+                }
             }
 
             return instance;
diff --git a/src/Lucene.Net/Support/ConcurrentHashSet.cs b/src/Lucene.Net/Support/ConcurrentHashSet.cs
index c728b39..57f3c52 100644
--- a/src/Lucene.Net/Support/ConcurrentHashSet.cs
+++ b/src/Lucene.Net/Support/ConcurrentHashSet.cs
@@ -24,6 +24,7 @@ SOFTWARE.
 
 */
 
+using Lucene.Net.Support.Threading;
 using System;
 using System.Collections;
 using System.Collections.Generic;
@@ -352,7 +353,9 @@ namespace Lucene.Net.Support
 
                 GetBucketAndLockNo(hashcode, out int bucketNo, out int lockNo, tables.Buckets.Length, tables.Locks.Length);
 
-                lock (tables.Locks[lockNo])
+                object syncRoot = tables.Locks[lockNo];
+                UninterruptableMonitor.Enter(syncRoot);
+                try
                 {
                     // If the table just got resized, we may not be holding the right lock, and must retry.
                     // This should be a rare occurrence.
@@ -383,6 +386,10 @@ namespace Lucene.Net.Support
                         previous = current;
                     }
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(syncRoot);
+                }
 
                 return false;
             }
@@ -478,7 +485,7 @@ namespace Lucene.Net.Support
                 try
                 {
                     if (acquireLock)
-                        Monitor.Enter(tables.Locks[lockNo], ref lockTaken);
+                        UninterruptableMonitor.Enter(tables.Locks[lockNo], ref lockTaken);
 
                     // If the table just got resized, we may not be holding the right lock, and must retry.
                     // This should be a rare occurrence.
@@ -519,7 +526,7 @@ namespace Lucene.Net.Support
                 finally
                 {
                     if (lockTaken)
-                        Monitor.Exit(tables.Locks[lockNo]);
+                        UninterruptableMonitor.Exit(tables.Locks[lockNo]);
                 }
 
                 //
@@ -709,7 +716,7 @@ namespace Lucene.Net.Support
                 var lockTaken = false;
                 try
                 {
-                    Monitor.Enter(locks[i], ref lockTaken);
+                    UninterruptableMonitor.Enter(locks[i], ref lockTaken);
                 }
                 finally
                 {
@@ -727,7 +734,7 @@ namespace Lucene.Net.Support
 
             for (var i = fromInclusive; i < toExclusive; i++)
             {
-                Monitor.Exit(_tables.Locks[i]);
+                UninterruptableMonitor.Exit(_tables.Locks[i]);
             }
         }
 
diff --git a/src/Lucene.Net/Support/ConcurrentSet.cs b/src/Lucene.Net/Support/ConcurrentSet.cs
index 5619801..eaba680 100644
--- a/src/Lucene.Net/Support/ConcurrentSet.cs
+++ b/src/Lucene.Net/Support/ConcurrentSet.cs
@@ -1,4 +1,5 @@
 using J2N.Text;
+using Lucene.Net.Support.Threading;
 using System;
 using System.Collections;
 using System.Collections.Generic;
@@ -42,92 +43,197 @@ namespace Lucene.Net.Support
 
         public bool Add(T item)
         {
-            lock (SyncRoot)
+            UninterruptableMonitor.Enter(SyncRoot);
+            try
+            {
                 return set.Add(item);
+            }
+            finally
+            {
+                UninterruptableMonitor.Exit(SyncRoot);
+            }
         }
 
         public void ExceptWith(IEnumerable<T> other)
         {
-            lock (SyncRoot)
+            UninterruptableMonitor.Enter(SyncRoot);
+            try
+            {
                 set.ExceptWith(other);
+            }
+            finally
+            {
+                UninterruptableMonitor.Exit(SyncRoot);
+            }
         }
 
         public void IntersectWith(IEnumerable<T> other)
         {
-            lock (SyncRoot)
+            UninterruptableMonitor.Enter(SyncRoot);
+            try
+            {
                 set.IntersectWith(other);
+            }
+            finally
+            {
+                UninterruptableMonitor.Exit(SyncRoot);
+            }
         }
 
         public bool IsProperSubsetOf(IEnumerable<T> other)
         {
-            lock (SyncRoot)
+            UninterruptableMonitor.Enter(SyncRoot);
+            try
+            {
                 return set.IsProperSubsetOf(other);
+            }
+            finally
+            {
+                UninterruptableMonitor.Exit(SyncRoot);
+            }
         }
 
         public bool IsProperSupersetOf(IEnumerable<T> other)
         {
-            lock (SyncRoot)
+            UninterruptableMonitor.Enter(SyncRoot);
+            try
+            {
                 return set.IsProperSupersetOf(other);
+            }
+            finally
+            {
+                UninterruptableMonitor.Exit(SyncRoot);
+            }
         }
 
         public bool IsSubsetOf(IEnumerable<T> other)
         {
-            lock (SyncRoot)
+            UninterruptableMonitor.Enter(SyncRoot);
+            try
+            {
                 return set.IsSubsetOf(other);
+            }
+            finally
+            {
+                UninterruptableMonitor.Exit(SyncRoot);
+            }
         }
 
         public bool IsSupersetOf(IEnumerable<T> other)
         {
-            lock (SyncRoot)
+            UninterruptableMonitor.Enter(SyncRoot);
+            try
+            {
                 return set.IsSupersetOf(other);
+            }
+            finally
+            {
+                UninterruptableMonitor.Exit(SyncRoot);
+            }
         }
 
         public bool Overlaps(IEnumerable<T> other)
         {
-            lock (SyncRoot)
+            UninterruptableMonitor.Enter(SyncRoot);
+            try
+            {
                 return set.Overlaps(other);
+            }
+            finally
+            {
+                UninterruptableMonitor.Exit(SyncRoot);
+            }
         }
 
         public bool SetEquals(IEnumerable<T> other)
         {
-            lock (SyncRoot)
+            UninterruptableMonitor.Enter(SyncRoot);
+            try
+            {
                 return set.SetEquals(other);
+            }
+            finally
+            {
+                UninterruptableMonitor.Exit(SyncRoot);
+            }
         }
 
         public void SymmetricExceptWith(IEnumerable<T> other)
         {
-            lock (SyncRoot)
+            UninterruptableMonitor.Enter(SyncRoot);
+            try
+            {
                 set.SymmetricExceptWith(other);
+            }
+            finally
+            {
+                UninterruptableMonitor.Exit(SyncRoot);
+            }
         }
 
         public void UnionWith(IEnumerable<T> other)
         {
-            lock (SyncRoot)
+            UninterruptableMonitor.Enter(SyncRoot);
+            try
+            {
                 set.UnionWith(other);
+            }
+            finally
+            {
+                UninterruptableMonitor.Exit(SyncRoot);
+            }
         }
 
         void ICollection<T>.Add(T item)
         {
-            lock (SyncRoot)
+            UninterruptableMonitor.Enter(SyncRoot);
+            try
+            {
                 set.Add(item);
+            }
+            finally
+            {
+                UninterruptableMonitor.Exit(SyncRoot);
+            }
         }
 
         public void Clear()
         {
-            lock (SyncRoot)
+            UninterruptableMonitor.Enter(SyncRoot);
+            try
+            {
                 set.Clear();
+            }
+            finally
+            {
+                UninterruptableMonitor.Exit(SyncRoot);
+            }
         }
 
         public bool Contains(T item)
         {
-            lock (SyncRoot)
+            UninterruptableMonitor.Enter(SyncRoot);
+            try
+            {
                 return set.Contains(item);
+            }
+            finally
+            {
+                UninterruptableMonitor.Exit(SyncRoot);
+            }
         }
 
         public void CopyTo(T[] array, int arrayIndex)
         {
-            lock (SyncRoot)
+            UninterruptableMonitor.Enter(SyncRoot);
+            try
+            {
                 set.CopyTo(array, arrayIndex);
+            }
+            finally
+            {
+                UninterruptableMonitor.Exit(SyncRoot);
+            }
         }
 
         void ICollection.CopyTo(Array array, int index)
@@ -167,11 +273,16 @@ namespace Lucene.Net.Support
 
                 try
                 {
-                    lock (SyncRoot)
+                    UninterruptableMonitor.Enter(SyncRoot);
+                    try
                     {
                         foreach (var item in set)
                             objects[index++] = item;
                     }
+                    finally
+                    {
+                        UninterruptableMonitor.Exit(SyncRoot);
+                    }
                 }
                 catch (ArrayTypeMismatchException)
                 {
@@ -185,8 +296,15 @@ namespace Lucene.Net.Support
         {
             get
             {
-                lock (SyncRoot)
+                UninterruptableMonitor.Enter(SyncRoot);
+                try
+                {
                     return set.Count;
+                }
+                finally
+                {
+                    UninterruptableMonitor.Exit(SyncRoot);
+                }
             }
         }
 
@@ -210,18 +328,30 @@ namespace Lucene.Net.Support
 
         public bool Remove(T item)
         {
-            lock (SyncRoot)
+            UninterruptableMonitor.Enter(SyncRoot);
+            try
+            {
                 return set.Remove(item);
+            }
+            finally
+            {
+                UninterruptableMonitor.Exit(SyncRoot);
+            }
         }
 
         public IEnumerator<T> GetEnumerator()
         {
             // Make a copy of the contents since enumeration is lazy and not thread-safe
             T[] array = new T[set.Count];
-            lock (SyncRoot)
+            UninterruptableMonitor.Enter(SyncRoot);
+            try
             {
                 set.CopyTo(array, 0);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(SyncRoot);
+            }
             return ((IEnumerable<T>)array).GetEnumerator();
         }
 
@@ -244,8 +374,15 @@ namespace Lucene.Net.Support
         /// <exception cref="ArgumentNullException">If <paramref name="comparer"/> is <c>null</c>.</exception>
         public bool Equals(object? other, IEqualityComparer comparer)
         {
-            lock (SyncRoot)
+            UninterruptableMonitor.Enter(SyncRoot);
+            try
+            {
                 return JCG.SetEqualityComparer<T>.Equals(set, other, comparer);
+            }
+            finally
+            {
+                UninterruptableMonitor.Exit(SyncRoot);
+            }
         }
 
         /// <summary>
@@ -257,8 +394,15 @@ namespace Lucene.Net.Support
         /// <returns>A hash code representing the current set.</returns>
         public int GetHashCode(IEqualityComparer comparer)
         {
-            lock (SyncRoot)
+            UninterruptableMonitor.Enter(SyncRoot);
+            try
+            {
                 return JCG.SetEqualityComparer<T>.GetHashCode(set, comparer);
+            }
+            finally
+            {
+                UninterruptableMonitor.Exit(SyncRoot);
+            }
         }
 
         /// <summary>
@@ -301,13 +445,18 @@ namespace Lucene.Net.Support
         /// </exception>
         public string ToString(string? format, IFormatProvider? formatProvider)
         {
-            lock (SyncRoot)
+            UninterruptableMonitor.Enter(SyncRoot);
+            try
             {
                 if (set is IFormattable formattable)
                     return formattable.ToString(format ?? "{0}", formatProvider);
 
                 return string.Format(formatProvider, format ?? "{0}", set);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(SyncRoot);
+            }
         }
 
         /// <summary>
diff --git a/src/Lucene.Net/Support/IO/StreamExtensions.cs b/src/Lucene.Net/Support/IO/StreamExtensions.cs
index f5b9fc0..e74c3d7 100644
--- a/src/Lucene.Net/Support/IO/StreamExtensions.cs
+++ b/src/Lucene.Net/Support/IO/StreamExtensions.cs
@@ -1,4 +1,5 @@
 using J2N.IO;
+using Lucene.Net.Support.Threading;
 using System;
 using System.IO;
 
@@ -81,7 +82,8 @@ namespace Lucene.Net.Support.IO
                 return 0;
 
             int read = 0;
-            lock (readLock)
+            UninterruptableMonitor.Enter(readLock);
+            try
             {
                 long originalPosition = stream.Position;
                 stream.Seek(position, SeekOrigin.Begin);
@@ -111,6 +113,10 @@ namespace Lucene.Net.Support.IO
                 // of the stream, so we return it as it was originally.
                 stream.Seek(originalPosition, SeekOrigin.Begin);
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(readLock);
+            }
 
             return read;
         }
diff --git a/src/Lucene.Net/Support/Threading/LimitedConcurrencyLevelTaskScheduler.cs b/src/Lucene.Net/Support/Threading/LimitedConcurrencyLevelTaskScheduler.cs
index 3e26cf5..ce807e4 100644
--- a/src/Lucene.Net/Support/Threading/LimitedConcurrencyLevelTaskScheduler.cs
+++ b/src/Lucene.Net/Support/Threading/LimitedConcurrencyLevelTaskScheduler.cs
@@ -87,8 +87,9 @@ namespace Lucene.Net.Support.Threading
         protected sealed override void QueueTask(Task task)
         {
             // Add the task to the list of tasks to be processed.  If there aren't enough 
-            // delegates currently queued or running to process tasks, schedule another. 
-            lock (_tasks)
+            // delegates currently queued or running to process tasks, schedule another.
+            UninterruptableMonitor.Enter(_tasks);
+            try
             {
                 _tasks.AddLast(task);
                 if (_delegatesQueuedOrRunning < _maxDegreeOfParallelism)
@@ -97,6 +98,10 @@ namespace Lucene.Net.Support.Threading
                     NotifyThreadPoolOfPendingWork();
                 }
             }
+            finally
+            {
+                UninterruptableMonitor.Exit(_tasks);
+            }
         }
 
         // Inform the ThreadPool that there's work to be executed for this scheduler. 
@@ -118,7 +123,8 @@ namespace Lucene.Net.Support.Threading
                     while (true)
                     {
                         Task item;
-                        lock (_tasks)
+                        UninterruptableMonitor.Enter(_tasks);
+                        try
                         {
                             // When there are no more items to be processed,
                             // note that we're done processing, and get out.
@@ -132,6 +138,10 @@ namespace Lucene.Net.Support.Threading
                             item = _tasks.First.Value;
                             _tasks.Remove(item);
                         }
+                        finally
+                        {
+                            UninterruptableMonitor.Exit(_tasks);
+                        }
 
                         // Execute the task we pulled out of the queue
                         base.TryExecuteTask(item);
@@ -162,7 +172,15 @@ namespace Lucene.Net.Support.Threading
         // Attempt to remove a previously scheduled task from the scheduler. 
         protected sealed override bool TryDequeue(Task task)
         {
-            lock (_tasks) return _tasks.Remove(task);
+            UninterruptableMonitor.Enter(_tasks);
+            try
+            {
+                return _tasks.Remove(task);
+            }
+            finally
+            {
+                UninterruptableMonitor.Exit(_tasks);
+            }
         }
 
         // Gets the maximum concurrency level supported by this scheduler. 
@@ -174,13 +192,13 @@ namespace Lucene.Net.Support.Threading
             bool lockTaken = false;
             try
             {
-                Monitor.TryEnter(_tasks, ref lockTaken);
+                UninterruptableMonitor.TryEnter(_tasks, ref lockTaken);
                 if (lockTaken) return _tasks;
                 else throw new NotSupportedException();
             }
             finally
             {
-                if (lockTaken) Monitor.Exit(_tasks);
+                if (lockTaken) UninterruptableMonitor.Exit(_tasks);
             }
         }
     }
diff --git a/src/Lucene.Net/Support/Threading/ReentrantLock.cs b/src/Lucene.Net/Support/Threading/ReentrantLock.cs
index 702a091..dd1359b 100644
--- a/src/Lucene.Net/Support/Threading/ReentrantLock.cs
+++ b/src/Lucene.Net/Support/Threading/ReentrantLock.cs
@@ -36,20 +36,20 @@ namespace Lucene.Net.Support.Threading
             // we enter the lock, then we immediately decrement it because that thread is no longer in the queue.
             // Due to race conditions, the queue length is an estimate only.
             Interlocked.Increment(ref _queueLength);
-            Monitor.Enter(_lock);
+            UninterruptableMonitor.Enter(_lock);
             Interlocked.Decrement(ref _queueLength);
         }
 
         // .NET Port: mimic ReentrantLock -- Monitor is re-entrant
         public void Unlock()
         {
-            Monitor.Exit(_lock);
+            UninterruptableMonitor.Exit(_lock);
         }
 
         public bool TryLock()
         {
             Interlocked.Increment(ref _queueLength);
-            bool success = Monitor.TryEnter(_lock);
+            bool success = UninterruptableMonitor.TryEnter(_lock);
             Interlocked.Decrement(ref _queueLength);
 
             return success;
@@ -69,6 +69,6 @@ namespace Lucene.Net.Support.Threading
 
         public bool HasQueuedThreads => _queueLength > 0;
 
-        public bool IsHeldByCurrentThread => Monitor.IsEntered(_lock);
+        public bool IsHeldByCurrentThread => UninterruptableMonitor.IsEntered(_lock);
     }
 }
\ No newline at end of file
diff --git a/src/Lucene.Net/Util/AttributeSource.cs b/src/Lucene.Net/Util/AttributeSource.cs
index cda26f4..c4114c0 100644
--- a/src/Lucene.Net/Util/AttributeSource.cs
+++ b/src/Lucene.Net/Util/AttributeSource.cs
@@ -1,6 +1,7 @@
 using Lucene.Net.Analysis.TokenAttributes;
 using Lucene.Net.Diagnostics;
 using Lucene.Net.Support;
+using Lucene.Net.Support.Threading;
 using System;
 using System.Collections;
 using System.Collections.Generic;
@@ -111,7 +112,8 @@ namespace Lucene.Net.Util
 
                     // LUCENENET: If the weakreference is dead, we need to explicitly update its key.
                     // We synchronize on attClassImplMapLock to make the operation atomic.
-                    lock (attClassImplMapLock)
+                    UninterruptableMonitor.Enter(attClassImplMapLock);
+                    try
                     {
                         if (!attClassImplMap.TryGetValue(attClass, out var @ref) || !@ref.TryGetTarget(out clazz))
                         {
@@ -123,6 +125,10 @@ namespace Lucene.Net.Util
 #endif
                         }
                     }
+                    finally
+                    {
+                        UninterruptableMonitor.Exit(attClassImplMapLock);
+                    }
 
                     return clazz;
                 }
diff --git a/src/Lucene.Net/Util/Fst/Util.cs b/src/Lucene.Net/Util/Fst/Util.cs
index 8e6c7b3..92bdf32 100644
--- a/src/Lucene.Net/Util/Fst/Util.cs
+++ b/src/Lucene.Net/Util/Fst/Util.cs
@@ -2,6 +2,7 @@
 using J2N.Numerics;
 using J2N.Text;
 using Lucene.Net.Diagnostics;
+using Lucene.Net.Support.Threading;
 using System;
 using System.Collections.Generic;
 using System.Globalization;
@@ -441,10 +442,15 @@ namespace Lucene.Net.Util.Fst
                     // so we need to add some thread safety just in case.
                     // Perhaps it might make sense to wrap SortedSet into a type
                     // that provides thread safety.
-                    lock (syncLock)
+                    UninterruptableMonitor.Enter(syncLock);
+                    try
                     {
                         queue.Remove(queue.Max);
                     }
+                    finally
+                    {
+                        UninterruptableMonitor.Exit(syncLock);
+                    }
                 }
             }
 
@@ -518,7 +524,8 @@ namespace Lucene.Net.Util.Fst
                     // so we need to add some thread safety just in case.
                     // Perhaps it might make sense to wrap SortedSet into a type
                     // that provides thread safety.
-                    lock (syncLock)
+                    UninterruptableMonitor.Enter(syncLock);
+                    try
                     {
                         path = queue.Min;
                         if (path != null)
@@ -526,6 +533,10 @@ namespace Lucene.Net.Util.Fst
                             queue.Remove(path);
                         }
                     }
+                    finally
+                    {
+                        UninterruptableMonitor.Exit(syncLock);
+                    }
 
                     if (path == null)
                     {
diff --git a/src/Lucene.Net/Util/InfoStream.cs b/src/Lucene.Net/Util/InfoStream.cs
index 7643ef5..243d66a 100644
--- a/src/Lucene.Net/Util/InfoStream.cs
+++ b/src/Lucene.Net/Util/InfoStream.cs
@@ -1,5 +1,6 @@
 using System;
 using Lucene.Net.Diagnostics;
+using Lucene.Net.Support.Threading;
 
 namespace Lucene.Net.Util
 {
@@ -68,20 +69,30 @@ namespace Lucene.Net.Util
         {
             get
             {
-                lock (typeof(InfoStream))
+                UninterruptableMonitor.Enter(typeof(InfoStream));
+                try
                 {
                     return defaultInfoStream;
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(typeof(InfoStream));
+                }
             }
             set
             {
-                lock (typeof(InfoStream))
+                UninterruptableMonitor.Enter(typeof(InfoStream));
+                try
                 {
                     defaultInfoStream = value ?? throw new ArgumentNullException(
                         nameof(Default),
                         "Cannot set InfoStream default implementation to null. " +
                         "To disable logging use InfoStream.NO_OUTPUT");
                 }
+                finally
+                {
+                    UninterruptableMonitor.Exit(typeof(InfoStream));
+                }
             }
         }