ReentrantReadWriteLock is an implementation of the Reentrant Lock interface. It has a Read and Write Lock.
Please see here for explanation of locks:
The idea is that read locks prevent the write lock getting the monitor. However a read lock thread does not block another read lock thread from reading.
However when a write lock takes the monitor, it blocks other write and read locks.
To get the code for this example:
git clone https://github.com/spotadev/java-examples.git
In both src/main/java and src/test/java navigate to this package:
com.javaspeak.java_examples.concurrency.lock.reentrantreadwritelock
You can run the testng unit test using a testng plugin for your IDE or you can run the main method of:
ReentrantReadWriteLockExampleTest
package com.javaspeak.java_examples.concurrency.lock.reentrantreadwritelock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* @author John Dickerson - 29 Nov 2022
*/
public interface ReentrantReadWriteLockExample {
Integer addToScore(
Score score,
Integer incrementToAddToScore,
ReentrantReadWriteLock lock );
Integer getScore(
Score score,
ReentrantReadWriteLock lock );
}
package com.javaspeak.java_examples.concurrency.lock.reentrantreadwritelock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
/**
* @author John Dickerson - 29 Nov 2022
*/
public class ReentrantReadWriteLockExampleImpl implements ReentrantReadWriteLockExample {
@Override
public Integer addToScore(
Score score,
Integer incrementToAddToScore,
ReentrantReadWriteLock lock ) {
WriteLock writeLock = lock.writeLock();
writeLock.lock();
try {
score.addToScore( incrementToAddToScore );
return incrementToAddToScore;
}
finally {
writeLock.unlock();
}
}
@Override
public Integer getScore(
Score score,
ReentrantReadWriteLock lock ) {
ReadLock readLock = lock.readLock();
readLock.lock();
try {
return score.getScore();
}
finally {
readLock.unlock();
}
}
}
package com.javaspeak.java_examples.concurrency.lock.reentrantreadwritelock;
/**
* @author John Dickerson - 29 Nov 2022
*/
public class Score {
private Integer score = 0;
public void addToScore( Integer number ) {
this.score = score + number;
}
public Integer getScore() {
return score;
}
}
package com.javaspeak.java_examples.concurrency.lock.reentrantreadwritelock;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.testng.Assert;
import org.testng.TestListenerAdapter;
import org.testng.TestNG;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
/**
* @author John Dickerson - 29 Nov 2022
*/
public class ReentrantReadWriteLockExampleTest {
private ReentrantReadWriteLockExample example;
@BeforeClass
public void setup() {
example = new ReentrantReadWriteLockExampleImpl();
}
@Test
public void doTest() throws InterruptedException, ExecutionException {
ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
Score sharedScore = new Score();
ExecutorService executorService = Executors.newFixedThreadPool( 8 );
List<Callable<Integer>> callables = new ArrayList<>();
Integer[] numbers = new Integer[] { 1, 1, 1, 1 };
for ( int i = 0; i < 4; i++ ) {
// needs to be a final as we are passing it into the perform method.
final Integer incrementToAdd = numbers[i];
// Callable is like a Runnable or Thread except it returns a value.
Callable<Integer> callable = new Callable<Integer>() {
public Integer call() throws Exception {
return example.addToScore(
sharedScore, incrementToAdd, readWriteLock );
}
};
callables.add( callable );
}
for ( int i = 0; i < 4; i++ ) {
Callable<Integer> callable = new Callable<Integer>() {
public Integer call() throws Exception {
return example.getScore(
sharedScore, readWriteLock );
}
};
callables.add( callable );
}
List<Future<Integer>> futures = executorService.invokeAll( callables );
for ( Future<Integer> future : futures ) {
future.get();
}
Assert.assertEquals( sharedScore.getScore().intValue(), 4 );
}
public static void main( String[] args ) {
TestListenerAdapter tla = new TestListenerAdapter();
TestNG testng = new TestNG();
testng.setTestClasses( new Class[] { ReentrantReadWriteLockExampleTest.class } );
testng.addListener( tla );
testng.run();
}
}
Back: Locks Explained | Concurrency
Page Author: JD