Surprise concurrent programming JUC series demo code address: github.com/mtcarpenter…

ReadWriteLock was introduced after Java 5. Locks such as Mutex and ReentrantLock are typically exclusive locks that allow only one thread to access them at a time. Read/write locks allow multiple reader threads to access at the same time, but all reader threads and other writer threads are blocked when the writer thread accesses them. Read-write locks maintain a pair of locks, a read lock and a write lock. By separating the read lock and the write lock, concurrency is greatly improved compared to the general exclusive lock. Access constraints on read/write locks:

  • Read - Read is not mutually exclusive: No blocking between reads
  • Read-write is mutually exclusive: Read blocks write, and write blocks read
  • Write - write is mutually exclusive: Write block

ReadWriteLock

ReentrantReadWriteLock is an implementation of the ReadWriteLock interface. ReadWriteLock defines only two methods to obtain a readLock and a writeLock, namely, the readLock() method and the writeLock() method.

public interface ReadWriteLock {

    Lock readLock(a);

    Lock writeLock(a);
}  Copy the code

In addition to interface methods, ReentrantReadWriteLock provides ways for outsiders to monitor its internal health.

  • int getReadLockCount(): Returns the number of times the current read lock was acquired. This number is not equal to the number of threads that have acquired the read lock. For example, if only one thread has acquired (reentered) the read lock n times, then the number of threads that occupy the read lock is 1, but this method returns N.
  • int getReadHoldCount(): Returns the number of times the current thread acquired the read lock. This method was added to ReentrantReadWriteLock in Java 6ThreadLocalSaving the current thread fetch count also makes Java 6 implementation more complicated
  • boolean isWriteLocked(): Checks whether the write lock is obtained
  • int getWriteHoldCount(): Returns the number of times the current write lock was acquired

ReentrantReadWriteLock

A simple cache can be implemented using ReentrantReadWriteLock as follows:

public class LockExample3 {

    private static final Map<String, Object> map = new HashMap<>();

    private static final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
  private static final Lock readLock = lock.readLock();   private static final Lock writeLock = lock.writeLock();    / * ** Store data to map *  * @param key  * @param value  * @return * /  public static Object put(String key, Object value) {  writeLock.lock();  try {  return map.put(key, value);  } finally {  writeLock.unlock();  }  }   / * ** Gets the value of a single key value *  * @param key  * @return * /  public static Object get(String key) {  readLock.lock();  try {  return map.get(key);  } finally {  readLock.unlock();  }  }   / * ** Get the map key *  * @return * /  public static Set<String> getAllKeys(a) {  readLock.lock();  try {  return map.keySet();  } finally {  readLock.unlock();  }  }    / * ** Clear all map data* /  public static void clear(a) {  writeLock.lock();  try {  map.clear();  } finally {  writeLock.unlock();  }  }  } Copy the code

The test code

public class LockExample3Test {

    // Total requests
    public static int requestTotal = 10;

  public static void main(String[] args) throws Exception {  ExecutorService executorService = Executors.newCachedThreadPool();  final CountDownLatch countDownLatch = new CountDownLatch(requestTotal);  for (int i = 0; i < requestTotal; i++) {  final String temp = String.valueOf(i);  executorService.execute(() -> {  try {  add(temp);  } catch (Exception e) {  }  countDownLatch.countDown();  });  }  // Wait for all threads to complete  countDownLatch.await();  // Multiple threads get key  for (int i = 0; i < requestTotal; i++) {  final String temp = String.valueOf(i);  executorService.execute(() -> {  try {  get(temp);  } catch (Exception e) {  }  });   }  executorService.shutdown();  TimeUnit.SECONDS.sleep(1);  // Get all keys  System.out.println("Get all keys \t" + LockExample3.getAllKeys());  // Clear all keys  LockExample3.clear();  // Retrieve all keys again and find that they have been emptied  System.out.println("Get all keys \t" + LockExample3.getAllKeys());   }   private static void add(String i) {  LockExample3.put(i, Thread.currentThread().getName());  }   private static void get(String i) {  System.out.println(i + "\t" + LockExample3.get(i));  } }  Copy the code

The running results are as follows:

0 pool-1-thread-1
1 pool-1-thread-2
2 pool-1-thread-3
4 pool-1-thread-5
3 pool-1-thread-4
8 pool-1-thread-9 7 pool-1-thread-8 6 pool-1-thread-7 5 pool-1-thread-6 9 pool-1-thread-10 Get all key values [0.1.2.3.4.5.6.7.8.9] Get all keys []Copy the code

Welcome to pay attention to the public number Shanma carpenter, I am Xiao Chun brother, engaged in Java back-end development, will be a little front-end, through the continuous output of a series of technical articles to literary friends, if this article can help you, welcome everyone to pay attention to, like, share support, we see you next period!