Updated code example and test case for mutex (#7642)
This commit is contained in:
		
							parent
							
								
									58595acd6f
								
							
						
					
					
						commit
						1888614f84
					
				| @ -1,11 +1,12 @@ | ||||
| package com.baeldung.concurrent.mutex; | ||||
| 
 | ||||
| public class SequenceGenerator { | ||||
| 
 | ||||
|     private int currentValue = 0; | ||||
| 
 | ||||
|     public int getNextSequence() throws InterruptedException { | ||||
|     public int getNextSequence() { | ||||
|         currentValue = currentValue + 1; | ||||
|         Thread.sleep(500); | ||||
|         return currentValue; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -4,15 +4,16 @@ import com.google.common.util.concurrent.Monitor; | ||||
| 
 | ||||
| public class SequenceGeneratorUsingMonitor extends SequenceGenerator { | ||||
| 
 | ||||
|     private Monitor monitor = new Monitor(); | ||||
|     private Monitor mutex = new Monitor(); | ||||
| 
 | ||||
|     @Override | ||||
|     public int getNextSequence() throws InterruptedException { | ||||
|         monitor.enter(); | ||||
|     public int getNextSequence() { | ||||
|         mutex.enter(); | ||||
|         try { | ||||
|             return super.getNextSequence(); | ||||
|         } finally { | ||||
|             monitor.leave(); | ||||
|             mutex.leave(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -7,7 +7,7 @@ public class SequenceGeneratorUsingReentrantLock extends SequenceGenerator { | ||||
|     private ReentrantLock mutex = new ReentrantLock(); | ||||
| 
 | ||||
|     @Override | ||||
|     public int getNextSequence() throws InterruptedException { | ||||
|     public int getNextSequence() { | ||||
|         try { | ||||
|             mutex.lock(); | ||||
|             return super.getNextSequence(); | ||||
| @ -15,4 +15,5 @@ public class SequenceGeneratorUsingReentrantLock extends SequenceGenerator { | ||||
|             mutex.unlock(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -7,12 +7,15 @@ public class SequenceGeneratorUsingSemaphore extends SequenceGenerator { | ||||
|     private Semaphore mutex = new Semaphore(1); | ||||
| 
 | ||||
|     @Override | ||||
|     public int getNextSequence() throws InterruptedException { | ||||
|     public int getNextSequence() { | ||||
|         try { | ||||
|             mutex.acquire(); | ||||
|             return super.getNextSequence(); | ||||
|         } catch (InterruptedException e) { | ||||
|             throw new RuntimeException("Exception in critical section.", e); | ||||
|         } finally { | ||||
|             mutex.release(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -2,9 +2,11 @@ package com.baeldung.concurrent.mutex; | ||||
| 
 | ||||
| public class SequenceGeneratorUsingSynchronizedBlock extends SequenceGenerator { | ||||
| 
 | ||||
|     private Object mutex = new Object(); | ||||
| 
 | ||||
|     @Override | ||||
|     public int getNextSequence() throws InterruptedException { | ||||
|         synchronized (this) { | ||||
|     public int getNextSequence() { | ||||
|         synchronized (mutex) { | ||||
|             return super.getNextSequence(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @ -3,7 +3,7 @@ package com.baeldung.concurrent.mutex; | ||||
| public class SequenceGeneratorUsingSynchronizedMethod extends SequenceGenerator { | ||||
| 
 | ||||
|     @Override | ||||
|     public synchronized int getNextSequence() throws InterruptedException { | ||||
|     public synchronized int getNextSequence() { | ||||
|         return super.getNextSequence(); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| package com.baeldung.concurrent.mutex; | ||||
| 
 | ||||
| import java.util.ArrayList; | ||||
| import java.util.HashSet; | ||||
| import java.util.LinkedHashSet; | ||||
| import java.util.List; | ||||
| import java.util.Set; | ||||
| import java.util.concurrent.ExecutorService; | ||||
| @ -12,59 +12,58 @@ import java.util.concurrent.TimeUnit; | ||||
| import org.junit.Assert; | ||||
| import org.junit.Test; | ||||
| 
 | ||||
| import com.baeldung.concurrent.mutex.SequenceGenerator; | ||||
| import com.baeldung.concurrent.mutex.SequenceGeneratorUsingMonitor; | ||||
| import com.baeldung.concurrent.mutex.SequenceGeneratorUsingReentrantLock; | ||||
| import com.baeldung.concurrent.mutex.SequenceGeneratorUsingSemaphore; | ||||
| import com.baeldung.concurrent.mutex.SequenceGeneratorUsingSynchronizedBlock; | ||||
| import com.baeldung.concurrent.mutex.SequenceGeneratorUsingSynchronizedMethod; | ||||
| 
 | ||||
| public class MutexUnitTest { | ||||
| 
 | ||||
|     private final int RANGE = 30; | ||||
| 
 | ||||
|     @Test | ||||
|     // @Test | ||||
|     // This test verifies the race condition use case, it may pass or fail based on execution environment | ||||
|     // Uncomment @Test to run it | ||||
|     public void givenUnsafeSequenceGenerator_whenRaceCondition_thenUnexpectedBehavior() throws Exception { | ||||
|         Set<Integer> uniqueSequences = getASetOFUniqueSequences(new SequenceGenerator()); | ||||
|         Assert.assertNotEquals(RANGE, uniqueSequences.size()); | ||||
|         int count = 1000; | ||||
|         Set<Integer> uniqueSequences = getUniqueSequences(new SequenceGenerator(), count); | ||||
|         Assert.assertNotEquals(count, uniqueSequences.size()); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void givenSequenceGeneratorUsingSynchronizedMethod_whenRaceCondition_thenSuccess() throws Exception { | ||||
|         Set<Integer> uniqueSequences = getASetOFUniqueSequences(new SequenceGeneratorUsingSynchronizedMethod()); | ||||
|         Assert.assertEquals(RANGE, uniqueSequences.size()); | ||||
|         int count = 1000; | ||||
|         Set<Integer> uniqueSequences = getUniqueSequences(new SequenceGeneratorUsingSynchronizedMethod(), count); | ||||
|         Assert.assertEquals(count, uniqueSequences.size()); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void givenSequenceGeneratorUsingSynchronizedBlock_whenRaceCondition_thenSuccess() throws Exception { | ||||
|         Set<Integer> uniqueSequences = getASetOFUniqueSequences(new SequenceGeneratorUsingSynchronizedBlock()); | ||||
|         Assert.assertEquals(RANGE, uniqueSequences.size()); | ||||
|         int count = 1000; | ||||
|         Set<Integer> uniqueSequences = getUniqueSequences(new SequenceGeneratorUsingSynchronizedBlock(), count); | ||||
|         Assert.assertEquals(count, uniqueSequences.size()); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void givenSequenceGeneratorUsingReentrantLock_whenRaceCondition_thenSuccess() throws Exception { | ||||
|         Set<Integer> uniqueSequences = getASetOFUniqueSequences(new SequenceGeneratorUsingReentrantLock()); | ||||
|         Assert.assertEquals(RANGE, uniqueSequences.size()); | ||||
|         int count = 1000; | ||||
|         Set<Integer> uniqueSequences = getUniqueSequences(new SequenceGeneratorUsingReentrantLock(), count); | ||||
|         Assert.assertEquals(count, uniqueSequences.size()); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void givenSequenceGeneratorUsingSemaphore_whenRaceCondition_thenSuccess() throws Exception { | ||||
|         Set<Integer> uniqueSequences = getASetOFUniqueSequences(new SequenceGeneratorUsingSemaphore()); | ||||
|         Assert.assertEquals(RANGE, uniqueSequences.size()); | ||||
|         int count = 1000; | ||||
|         Set<Integer> uniqueSequences = getUniqueSequences(new SequenceGeneratorUsingSemaphore(), count); | ||||
|         Assert.assertEquals(count, uniqueSequences.size()); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void givenSequenceGeneratorUsingMonitor_whenRaceCondition_thenSuccess() throws Exception { | ||||
|         Set<Integer> uniqueSequences = getASetOFUniqueSequences(new SequenceGeneratorUsingMonitor()); | ||||
|         Assert.assertEquals(RANGE, uniqueSequences.size()); | ||||
|         int count = 1000; | ||||
|         Set<Integer> uniqueSequences = getUniqueSequences(new SequenceGeneratorUsingMonitor(), count); | ||||
|         Assert.assertEquals(count, uniqueSequences.size()); | ||||
|     } | ||||
| 
 | ||||
|     private Set<Integer> getASetOFUniqueSequences(SequenceGenerator generator) throws Exception { | ||||
|     private Set<Integer> getUniqueSequences(SequenceGenerator generator, int count) throws Exception { | ||||
|         ExecutorService executor = Executors.newFixedThreadPool(3); | ||||
|         Set<Integer> uniqueSequences = new HashSet<>(); | ||||
|         Set<Integer> uniqueSequences = new LinkedHashSet<>(); | ||||
|         List<Future<Integer>> futures = new ArrayList<>(); | ||||
| 
 | ||||
|         for (int i = 0; i < RANGE; i++) { | ||||
|         for (int i = 0; i < count; i++) { | ||||
|             futures.add(executor.submit(generator::getNextSequence)); | ||||
|         } | ||||
| 
 | ||||
| @ -72,7 +71,7 @@ public class MutexUnitTest { | ||||
|             uniqueSequences.add(future.get()); | ||||
|         } | ||||
| 
 | ||||
|         executor.awaitTermination(15, TimeUnit.SECONDS); | ||||
|         executor.awaitTermination(1, TimeUnit.SECONDS); | ||||
|         executor.shutdown(); | ||||
| 
 | ||||
|         return uniqueSequences; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user