Code example: Using a Mutex Object in Java (#7587)
This commit is contained in:
parent
b3547bc783
commit
4562a2fa07
@ -0,0 +1,11 @@
|
|||||||
|
package com.baeldung.concurrent.mutex;
|
||||||
|
|
||||||
|
public class SequenceGenerator {
|
||||||
|
private int currentValue = 0;
|
||||||
|
|
||||||
|
public int getNextSequence() throws InterruptedException {
|
||||||
|
currentValue = currentValue + 1;
|
||||||
|
Thread.sleep(500);
|
||||||
|
return currentValue;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package com.baeldung.concurrent.mutex;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.Monitor;
|
||||||
|
|
||||||
|
public class SequenceGeneratorUsingMonitor extends SequenceGenerator {
|
||||||
|
|
||||||
|
private Monitor monitor = new Monitor();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getNextSequence() throws InterruptedException {
|
||||||
|
monitor.enter();
|
||||||
|
try {
|
||||||
|
return super.getNextSequence();
|
||||||
|
} finally {
|
||||||
|
monitor.leave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package com.baeldung.concurrent.mutex;
|
||||||
|
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
|
public class SequenceGeneratorUsingReentrantLock extends SequenceGenerator {
|
||||||
|
|
||||||
|
private ReentrantLock mutex = new ReentrantLock();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getNextSequence() throws InterruptedException {
|
||||||
|
try {
|
||||||
|
mutex.lock();
|
||||||
|
return super.getNextSequence();
|
||||||
|
} finally {
|
||||||
|
mutex.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package com.baeldung.concurrent.mutex;
|
||||||
|
|
||||||
|
import java.util.concurrent.Semaphore;
|
||||||
|
|
||||||
|
public class SequenceGeneratorUsingSemaphore extends SequenceGenerator {
|
||||||
|
|
||||||
|
private Semaphore mutex = new Semaphore(1);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getNextSequence() throws InterruptedException {
|
||||||
|
try {
|
||||||
|
mutex.acquire();
|
||||||
|
return super.getNextSequence();
|
||||||
|
} finally {
|
||||||
|
mutex.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package com.baeldung.concurrent.mutex;
|
||||||
|
|
||||||
|
public class SequenceGeneratorUsingSynchronizedBlock extends SequenceGenerator {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getNextSequence() throws InterruptedException {
|
||||||
|
synchronized (this) {
|
||||||
|
return super.getNextSequence();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.baeldung.concurrent.mutex;
|
||||||
|
|
||||||
|
public class SequenceGeneratorUsingSynchronizedMethod extends SequenceGenerator {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized int getNextSequence() throws InterruptedException {
|
||||||
|
return super.getNextSequence();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,81 @@
|
|||||||
|
package com.baeldung.concurrent.mutex;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
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
|
||||||
|
public void givenUnsafeSequenceGenerator_whenRaceCondition_thenUnexpectedBehavior() throws Exception {
|
||||||
|
Set<Integer> uniqueSequences = getASetOFUniqueSequences(new SequenceGenerator());
|
||||||
|
Assert.assertNotEquals(RANGE, uniqueSequences.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenSequenceGeneratorUsingSynchronizedMethod_whenRaceCondition_thenSuccess() throws Exception {
|
||||||
|
Set<Integer> uniqueSequences = getASetOFUniqueSequences(new SequenceGeneratorUsingSynchronizedMethod());
|
||||||
|
Assert.assertEquals(RANGE, uniqueSequences.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenSequenceGeneratorUsingSynchronizedBlock_whenRaceCondition_thenSuccess() throws Exception {
|
||||||
|
Set<Integer> uniqueSequences = getASetOFUniqueSequences(new SequenceGeneratorUsingSynchronizedBlock());
|
||||||
|
Assert.assertEquals(RANGE, uniqueSequences.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenSequenceGeneratorUsingReentrantLock_whenRaceCondition_thenSuccess() throws Exception {
|
||||||
|
Set<Integer> uniqueSequences = getASetOFUniqueSequences(new SequenceGeneratorUsingReentrantLock());
|
||||||
|
Assert.assertEquals(RANGE, uniqueSequences.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenSequenceGeneratorUsingSemaphore_whenRaceCondition_thenSuccess() throws Exception {
|
||||||
|
Set<Integer> uniqueSequences = getASetOFUniqueSequences(new SequenceGeneratorUsingSemaphore());
|
||||||
|
Assert.assertEquals(RANGE, uniqueSequences.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenSequenceGeneratorUsingMonitor_whenRaceCondition_thenSuccess() throws Exception {
|
||||||
|
Set<Integer> uniqueSequences = getASetOFUniqueSequences(new SequenceGeneratorUsingMonitor());
|
||||||
|
Assert.assertEquals(RANGE, uniqueSequences.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<Integer> getASetOFUniqueSequences(SequenceGenerator generator) throws Exception {
|
||||||
|
ExecutorService executor = Executors.newFixedThreadPool(3);
|
||||||
|
Set<Integer> uniqueSequences = new HashSet<>();
|
||||||
|
List<Future<Integer>> futures = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < RANGE; i++) {
|
||||||
|
futures.add(executor.submit(generator::getNextSequence));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Future<Integer> future : futures) {
|
||||||
|
uniqueSequences.add(future.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
executor.awaitTermination(15, TimeUnit.SECONDS);
|
||||||
|
executor.shutdown();
|
||||||
|
|
||||||
|
return uniqueSequences;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user