public virtual void TestAccquireReleaseRace() { DocumentsWriterStallControl ctrl = new DocumentsWriterStallControl(); ctrl.UpdateStalled(false); AtomicBoolean stop = new AtomicBoolean(false); AtomicBoolean checkPoint = new AtomicBoolean(true); int numStallers = AtLeast(1); int numReleasers = AtLeast(1); int numWaiters = AtLeast(1); var sync = new Synchronizer(numStallers + numReleasers, numStallers + numReleasers + numWaiters); var threads = new ThreadJob[numReleasers + numStallers + numWaiters]; IList <Exception> exceptions = new SynchronizedList <Exception>(); for (int i = 0; i < numReleasers; i++) { threads[i] = new Updater(stop, checkPoint, ctrl, sync, true, exceptions); } for (int i = numReleasers; i < numReleasers + numStallers; i++) { threads[i] = new Updater(stop, checkPoint, ctrl, sync, false, exceptions); } for (int i = numReleasers + numStallers; i < numReleasers + numStallers + numWaiters; i++) { threads[i] = new Waiter(stop, checkPoint, ctrl, sync, exceptions); } Start(threads); int iters = AtLeast(10000); float checkPointProbability = TestNightly ? 0.5f : 0.1f; for (int i = 0; i < iters; i++) { if (checkPoint) { Assert.IsTrue(sync.updateJoin.Wait(new TimeSpan(0, 0, 0, 10)), "timed out waiting for update threads - deadlock?"); if (exceptions.Count > 0) { foreach (Exception throwable in exceptions) { Console.WriteLine(throwable.ToString()); Console.Write(throwable.StackTrace); } Assert.Fail("got exceptions in threads"); } if (ctrl.HasBlocked && ctrl.IsHealthy) { AssertState(numReleasers, numStallers, numWaiters, threads, ctrl); } checkPoint.Value = (false); sync.waiter.Signal(); sync.leftCheckpoint.Wait(); } Assert.IsFalse(checkPoint); Assert.AreEqual(0, sync.waiter.CurrentCount); if (checkPointProbability >= (float)Random.NextDouble()) { sync.Reset(numStallers + numReleasers, numStallers + numReleasers + numWaiters); checkPoint.Value = (true); } } if (!checkPoint) { sync.Reset(numStallers + numReleasers, numStallers + numReleasers + numWaiters); checkPoint.Value = (true); } Assert.IsTrue(sync.updateJoin.Wait(new TimeSpan(0, 0, 0, 10))); AssertState(numReleasers, numStallers, numWaiters, threads, ctrl); checkPoint.Value = (false); stop.Value = (true); sync.waiter.Signal(); sync.leftCheckpoint.Wait(); for (int i = 0; i < threads.Length; i++) { ctrl.UpdateStalled(false); threads[i].Join(2000); if (threads[i].IsAlive && threads[i] is Waiter) { if (threads[i].State == ThreadState.WaitSleepJoin) { Assert.Fail("waiter is not released - anyThreadsStalled: " + ctrl.AnyStalledThreads()); } } } }
public virtual void TestThreadSafety() { Directory dir = NewDirectory(); // NOTE: this also controls the number of threads! int n = TestUtil.NextInt32(Random, 20, 40); IndexWriter writer = new IndexWriter(dir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random))); for (int i = 0; i < n; i++) { writer.AddDocument(CreateDocument(i, 3)); } writer.ForceMerge(1); writer.Dispose(); TestReopen test = new TestReopenAnonymousClass3(this, dir, n); IList <ReaderCouple> readers = new SynchronizedList <ReaderCouple>(); DirectoryReader firstReader = DirectoryReader.Open(dir); DirectoryReader reader = firstReader; ReaderThread[] threads = new ReaderThread[n]; ISet <DirectoryReader> readersToClose = new JCG.HashSet <DirectoryReader>().AsConcurrent(); for (int i = 0; i < n; i++) { if (i % 2 == 0) { DirectoryReader refreshed = DirectoryReader.OpenIfChanged(reader); if (refreshed != null) { readersToClose.Add(reader); reader = refreshed; } } DirectoryReader r = reader; int index = i; ReaderThreadTask task; if (i < 4 || (i >= 10 && i < 14) || i > 18) { task = new ReaderThreadTaskAnonymousClass(this, test, readers, readersToClose, r, index); } else { task = new ReaderThreadTaskAnonymousClass2(this, readers); } threads[i] = new ReaderThread(task); threads[i].Start(); } lock (this) { Monitor.Wait(this, TimeSpan.FromMilliseconds(1000)); } for (int i = 0; i < n; i++) { if (threads[i] != null) { threads[i].StopThread(); } } for (int i = 0; i < n; i++) { if (threads[i] != null) { threads[i].Join(); if (threads[i].error != null) { string msg = "Error occurred in thread " + threads[i].Name + ":\n" + threads[i].error.Message; Assert.Fail(msg); } } } foreach (DirectoryReader readerToClose in readersToClose) { readerToClose.Dispose(); } firstReader.Dispose(); reader.Dispose(); foreach (DirectoryReader readerToClose in readersToClose) { AssertReaderClosed(readerToClose, true); } AssertReaderClosed(reader, true); AssertReaderClosed(firstReader, true); dir.Dispose(); }