Package tenapull.sync

Class ReadWriteLock<O,​R>

java.lang.Object
tenapull.sync.ReadWriteLock<O,​R>
Type Parameters:
O - the object for which read/write access needs to be synchronized
R - the standard return value from the read/write lambdas. Other values types can also be returned with the overloaded methods

public class ReadWriteLock<O,​R>
extends java.lang.Object
Simple class for synchronizing concurrent read access and exclusive write access to an object. The Object is passed into the constructor, and should only be accessed via lambdas submitted to the read() or write() methods. The object will be provided as the argument to these lambdas.

It is entirely up to the implementation to honor read and write rules. This class simply helps to synchronize those operations. However, the implementation may choose to submit both the object AND an unmodifiable view of the object to the ReadWriteLock constructor, where the original object will be sent to write lambdas and the unmodifiable view will be sent read lambdas. If only one argument is submitted, the same object is sent to both. Alternatively, you may pass a single Map, Set, List, or Collection to the respective static methods which create an unmodifiable view of the original that is used for reading in a new ReadWriteLock instance (the original, of course, will be used for writing).

Mechanics:

Multiple threads can read at one time. Only one thread can write at a time, and no other threads can read while the write thread holds the lock. Note that the write thread will still be able to run read lambdas with the read() method while holding the write lock.

More importantly, a thread with only a read lock must release all read locks BEFORE it requests a write lock. Otherwise it could lead to a deadlock if multiple threads are doing this simultaneously, but an ConcurrentAccessException will be thrown to prevent this.

Type Parameters: * O : Object type, of the object needing synchronized access and passed into the constructor. This will also * be the object and type submitted to the read and write lambdas * * R : Return type from the most commonly used lambda. Typically, this is the type being held in the list/map/set * being synchronized. You can return null and ignore the return value if it is not needed. If you need a * different return type under varying situations, this can be specified on a per-invocation basis using * read/write(Class<T> returnType, Callable<O, T> lambda)

  • Nested Class Summary

    Nested Classes 
    Modifier and Type Class Description
    class  ReadWriteLock.ReadThreadsIterator
    A special iterator to handle dynamically changing state of read lock threads, for the ReadThreadsSet
    static class  ReadWriteLock.ThreadDisruption
    Error (NOT Exception) thrown when a disruptable thread would create a deadlock if allowed the request read/write access.
  • Constructor Summary

    Constructors 
    Constructor Description
    ReadWriteLock​(O objectToLock)
    Instantiates a new Read write lock that synchronizes access to the given object.
    ReadWriteLock​(O objectToLock, O unmodifiableView)
    Instantiates a new Read write lock that synchronizes access to the given object, and the given unmodifiable view of this object
  • Method Summary

    Modifier and Type Method Description
    static <R,​ T> ReadWriteLock<java.util.Collection<T>,​R> forCollection​(java.util.Collection<T> collection)
    Creates a ReadWriteLock with the given collection for writing, and an unmodifiable view of the collection for reading
    static <T,​ R> ReadWriteLock<java.util.List<T>,​R> forList​(java.util.List<T> list)
    Creates a ReadWriteLock with the given list for writing, and an unmodifiable view of the list for reading
    static <K,​ V,​ R> ReadWriteLock<java.util.Map<K,​V>,​R> forMap​(java.util.Map<K,​V> map)
    Creates a ReadWriteLock with the given map for writing, and an unmodifiable view of the map for reading
    static <T,​ R> ReadWriteLock<java.util.Set<T>,​R> forSet​(java.util.Set<T> set)
    Creates a ReadWriteLock with the given set for writing, and an unmodifiable view of the set for reading
    java.util.Set<java.lang.Thread> getCurrentReadThreads()
    Gets an unmodifiable view of the set of threads currently holding a read lock on this ReadWriteLock
    java.lang.Thread getCurrentWriteThread()
    Returns the thread that currently holds the write lock on this ReadWriteLock, if any
    static RecursiveMap<java.lang.Thread> getThreadBlockingMap()
    Gets the recursive map of which threads are blocking which other threads from obtaining locks, across all instances of ReadWriteLock
    java.util.Set<java.lang.Thread> getThreadsBlockedBy​(java.lang.Thread thread)
    Gets the set of all threads which are blocked by the provided thread within the context of this ReadWriteLock
    boolean holdsLock()
    Find out if the current thread holds any lock (read or write) on this ReadWriteLock
    boolean holdsReadLock()
    Find out if the current thread holds a read lock on this ReadWriteLock
    boolean holdsReadLock​(java.lang.Thread thread)
    Find out if the provided thread holds a read lock on this ReadWriteLock
    boolean holdsWriteLock()
    Find out if the current thread holds the write lock on this ReadWriteLock
    boolean holdsWriteLock​(java.lang.Thread thread)
    Find out if the provided thread holds the write lock on this ReadWriteLock
    static boolean isBlockingAnyLock​(java.lang.Thread thread)
    Determine whether the current thread is blocking the provided thread from obtaining any locks (read or write) in any instance of ReadWriteLock
    boolean isCurrentBlocking​(java.lang.Thread thread)
    Returns whether the current thread is blocking the provided thread from obtaining a read or write lock from this ReadWriteLock instance
    static boolean isWaitingForAnyLock​(java.lang.Thread thread)
    Determine whether the provided thread is waiting for a lock (read or write) in any instance of ReadWriteLock
    static boolean isWaitingForAnyReadLock​(java.lang.Thread thread)
    Determine whether the provided thread is waiting for a read lock in any instance of ReadWriteLock
    static boolean isWaitingForAnyWriteLock​(java.lang.Thread thread)
    Determine whether the provided thread is waiting for a write lock in any instance of ReadWriteLock
    boolean isWaitingForLock​(java.lang.Thread thread)
    Returns whether the provided thread is waiting for any lock (read or write)
    boolean isWaitingForReadLock​(java.lang.Thread thread)
    Returns whether the provided thread is waiting for a read lock
    boolean isWaitingForWriteLock​(java.lang.Thread thread)
    Returns whether the provided thread is waiting for a write lock
    <T> T read​(java.lang.Class<T> returnType, Lambda1<O,​T> lambda)
    Grants read access to the provided lambda, allowing it to return any type
    R read​(Lambda1<O,​R> lambda)
    Grants read access to the provided lambda, allowing it to return the standard return type
    static void registerAsDisruptable​(java.lang.Thread disruptableThread)
    Register the provided thread as a "disruptable" thread, meaning that it may be denied read/write access if doing so would lead to a circular blocking pattern that would result in deadlock
    <T> T write​(java.lang.Class<T> returnType, Lambda1<O,​T> lambda)
    Grants write access to the provided lambda, allowing it to return any type
    R write​(Lambda1<O,​R> lambda)
    Grants write access to the provided lambda, allowing it to return the standard return type

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Constructor Details

    • ReadWriteLock

      public ReadWriteLock​(O objectToLock)
      Instantiates a new Read write lock that synchronizes access to the given object.
      Parameters:
      objectToLock - the object to lock
    • ReadWriteLock

      public ReadWriteLock​(O objectToLock, O unmodifiableView)
      Instantiates a new Read write lock that synchronizes access to the given object, and the given unmodifiable view of this object
      Parameters:
      objectToLock - the object to lock
      unmodifiableView - the unmodifiable view of the object to lock
  • Method Details

    • forMap

      public static <K,​ V,​ R> ReadWriteLock<java.util.Map<K,​V>,​R> forMap​(java.util.Map<K,​V> map)
      Creates a ReadWriteLock with the given map for writing, and an unmodifiable view of the map for reading
      Type Parameters:
      K - the key type for the map
      V - the value type for the map
      R - the standard return type
      Parameters:
      map - the map
      Returns:
      the read write lock
    • forSet

      public static <T,​ R> ReadWriteLock<java.util.Set<T>,​R> forSet​(java.util.Set<T> set)
      Creates a ReadWriteLock with the given set for writing, and an unmodifiable view of the set for reading
      Type Parameters:
      T - the set type param
      R - the standard return type
      Parameters:
      set - the set
      Returns:
      the read write lock
    • forList

      public static <T,​ R> ReadWriteLock<java.util.List<T>,​R> forList​(java.util.List<T> list)
      Creates a ReadWriteLock with the given list for writing, and an unmodifiable view of the list for reading
      Type Parameters:
      T - the list type param
      R - the standard return type
      Parameters:
      list - the list
      Returns:
      the read write lock
    • forCollection

      public static <R,​ T> ReadWriteLock<java.util.Collection<T>,​R> forCollection​(java.util.Collection<T> collection)
      Creates a ReadWriteLock with the given collection for writing, and an unmodifiable view of the collection for reading
      Type Parameters:
      T - the collection type param
      R - the standard return type
      Parameters:
      collection - the collection
      Returns:
      the read write lock
    • read

      public final R read​(Lambda1<O,​R> lambda)
      Grants read access to the provided lambda, allowing it to return the standard return type
      Parameters:
      lambda - the lambda
      Returns:
      the value returned by the lambda
    • write

      public final R write​(Lambda1<O,​R> lambda) throws javax.ejb.ConcurrentAccessException
      Grants write access to the provided lambda, allowing it to return the standard return type
      Parameters:
      lambda - the lambda
      Returns:
      the value returned by the lambda
      Throws:
      javax.ejb.ConcurrentAccessException - if the invoking thread already holds a read lock for this ReadWriteLock instance. It must release the read lock before requesting a write lock
    • read

      public final <T> T read​(java.lang.Class<T> returnType, Lambda1<O,​T> lambda)
      Grants read access to the provided lambda, allowing it to return any type
      Type Parameters:
      T - the type parameter
      Parameters:
      returnType - the return type
      lambda - the lambda
      Returns:
      the value returned by the lambda
    • write

      public final <T> T write​(java.lang.Class<T> returnType, Lambda1<O,​T> lambda) throws javax.ejb.ConcurrentAccessException
      Grants write access to the provided lambda, allowing it to return any type
      Type Parameters:
      T - the type parameter
      Parameters:
      returnType - the return type
      lambda - the lambda
      Returns:
      the value returned by the lambda
      Throws:
      javax.ejb.ConcurrentAccessException - if the invoking thread already holds a read lock for this ReadWriteLock instance. It must release the read lock before requesting a write lock
    • holdsWriteLock

      public final boolean holdsWriteLock()
      Find out if the current thread holds the write lock on this ReadWriteLock
      Returns:
      true if the current thread holds the write lock, false if not
    • holdsWriteLock

      public final boolean holdsWriteLock​(java.lang.Thread thread)
      Find out if the provided thread holds the write lock on this ReadWriteLock
      Parameters:
      thread - the thread to check
      Returns:
      true if the provided thread holds the write lock, false if not
    • holdsReadLock

      public final boolean holdsReadLock()
      Find out if the current thread holds a read lock on this ReadWriteLock
      Returns:
      true if the current thread holds a read lock, false if not
    • holdsReadLock

      public final boolean holdsReadLock​(java.lang.Thread thread)
      Find out if the provided thread holds a read lock on this ReadWriteLock
      Parameters:
      thread - the thread to check
      Returns:
      true if the provided thread holds a read lock, false if not
    • holdsLock

      public final boolean holdsLock()
      Find out if the current thread holds any lock (read or write) on this ReadWriteLock
      Returns:
      true if the current thread holds a lock, false if not
    • getCurrentWriteThread

      public final java.lang.Thread getCurrentWriteThread()
      Returns the thread that currently holds the write lock on this ReadWriteLock, if any
      Returns:
      that thread that currently holds the write lock, or null if none does
    • isCurrentBlocking

      public final boolean isCurrentBlocking​(java.lang.Thread thread)
      Returns whether the current thread is blocking the provided thread from obtaining a read or write lock from this ReadWriteLock instance
      Parameters:
      thread - the thread that may or may not be blocked
      Returns:
      boolean whether this thread is blocking it
    • isWaitingForReadLock

      public boolean isWaitingForReadLock​(java.lang.Thread thread)
      Returns whether the provided thread is waiting for a read lock
      Parameters:
      thread - the thread to check
      Returns:
      whether the thread is waiting for a read lock
    • isWaitingForWriteLock

      public boolean isWaitingForWriteLock​(java.lang.Thread thread)
      Returns whether the provided thread is waiting for a write lock
      Parameters:
      thread - the thread to check
      Returns:
      whether the thread is waiting for a write lock
    • isWaitingForLock

      public boolean isWaitingForLock​(java.lang.Thread thread)
      Returns whether the provided thread is waiting for any lock (read or write)
      Parameters:
      thread - the thread to check
      Returns:
      whether the thread is waiting for a lock
    • getThreadsBlockedBy

      public java.util.Set<java.lang.Thread> getThreadsBlockedBy​(java.lang.Thread thread)
      Gets the set of all threads which are blocked by the provided thread within the context of this ReadWriteLock
      Parameters:
      thread - the thread that may be blocking other threads
      Returns:
      the threads blocked by the provided thread
    • registerAsDisruptable

      public static void registerAsDisruptable​(java.lang.Thread disruptableThread)
      Register the provided thread as a "disruptable" thread, meaning that it may be denied read/write access if doing so would lead to a circular blocking pattern that would result in deadlock
      Parameters:
      disruptableThread - the disruptable thread
    • getThreadBlockingMap

      public static RecursiveMap<java.lang.Thread> getThreadBlockingMap()
      Gets the recursive map of which threads are blocking which other threads from obtaining locks, across all instances of ReadWriteLock
      Returns:
      the thread blocking map
    • isBlockingAnyLock

      public static boolean isBlockingAnyLock​(java.lang.Thread thread)
      Determine whether the current thread is blocking the provided thread from obtaining any locks (read or write) in any instance of ReadWriteLock
      Parameters:
      thread - the thread that may be blocked
      Returns:
      whether the current thread is blocking the provided thread
    • isWaitingForAnyReadLock

      public static boolean isWaitingForAnyReadLock​(java.lang.Thread thread)
      Determine whether the provided thread is waiting for a read lock in any instance of ReadWriteLock
      Parameters:
      thread - the thread to check
      Returns:
      true if the provided thread is waiting for any read lock
    • isWaitingForAnyWriteLock

      public static boolean isWaitingForAnyWriteLock​(java.lang.Thread thread)
      Determine whether the provided thread is waiting for a write lock in any instance of ReadWriteLock
      Parameters:
      thread - the thread to check
      Returns:
      true if the provided thread is waiting for any write lock
    • isWaitingForAnyLock

      public static boolean isWaitingForAnyLock​(java.lang.Thread thread)
      Determine whether the provided thread is waiting for a lock (read or write) in any instance of ReadWriteLock
      Parameters:
      thread - the thread to check
      Returns:
      true if the provided thread is waiting for any lock (read or write)
    • getCurrentReadThreads

      public final java.util.Set<java.lang.Thread> getCurrentReadThreads()
      Gets an unmodifiable view of the set of threads currently holding a read lock on this ReadWriteLock
      Returns:
      the current read threads