Skip to content

Latest commit

 

History

History
172 lines (152 loc) · 5.4 KB

File metadata and controls

172 lines (152 loc) · 5.4 KB

Locks

Objective
Use Lock, ReadWriteLock, and ReentrantLock classes in the java.util.concurrent.locks and java.util.concurrent.atomic packages to support lock-free thread-safe programming on single variables

The Lock, ReadWriteLock and ReentrantLock classes and interfaces allow for different types of Locks. These Locks are used so that a limited number of threads have access to the same variable at any given time, or so that only one of them can change its value.

In this section examples will be presented using these classes and interfaces. As in other sections of this chapter, examples can be large when creating threads is required. Take more time to fully understand them.

Reentrant Lock

  1. You can get a Lock using the ReentrantLock class.

    src/org/j6toj8/concurrency/locks/Locks_ReentrantLock.java
    link:../../../src/org/j6toj8/concurrency/locks/Locks_ReentrantLock.java[role=include]
    console output
    ABC

    Note that lock is removed within a finally block. This ensures that a thread will not have an lock indefinitely.

  2. Calling the unlock method without previously locking will throw an exception.

    src/org/j6toj8/concurrency/locks/Locks_UnlockWithoutLock.java
    link:../../../src/org/j6toj8/concurrency/locks/Locks_UnlockWithoutLock.java[role=include]
    console output
    ABC
    Exception in thread "main" java.lang.IllegalMonitorStateException
    	at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:151)
    	at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261)
    	at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:457)
    	at org.j6toj8.concurrency.locks.Locks_UnlockWithoutLock.main(Locks_UnlockWithoutLock.java:14)
  3. You can try to get a lock immediately using the tryLock method.

    src/org/j6toj8/concurrency/locks/Locks_TryLock.java
    link:../../../src/org/j6toj8/concurrency/locks/Locks_TryLock.java[role=include]
    console output
    ABC
  4. You can also try to get a lock by setting a maximum wait time.

    src/org/j6toj8/concurrency/locks/Locks_TryLockTimeout.java
    link:../../../src/org/j6toj8/concurrency/locks/Locks_TryLockTimeout.java[role=include]
    console output
    ABC
  5. In a scenario with multiple threads, only one of them may be able to obtain a lock.

    src/org/j6toj8/concurrency/locks/Locks_TryLockMultithread.java
    link:../../../src/org/j6toj8/concurrency/locks/Locks_TryLockMultithread.java[role=include]
    console output
    Thread-0: Got the Lock
    Thread-2: Got the Lock

    In this 3 threads run, only two were able to get lock immediately and print to the console. But the result is unpredictable. There may be executions where all will get the lock, and others where only one thread will succeed.

  6. A thread can get more than one lock on the same Lock object, but must undo lock multiple times as well.

    src/org/j6toj8/concurrency/locks/Locks_LockTwice.java
    link:../../../src/org/j6toj8/concurrency/locks/Locks_LockTwice.java[role=include]
    console output
    ABC

    Since the thread called the lock twice, if it had not called unlock twice, another thread would not be able to get the lock.

  7. You can ensure a more "fair" distribution of locks by passing true as an argument to ReentrantLock.

    src/org/j6toj8/concurrency/locks/Locks_Fair.java
    link:../../../src/org/j6toj8/concurrency/locks/Locks_Fair.java[role=include]

    When passing the true argument, when multiple threads are waiting for the same lock, it will be given to that thread that has been waiting the longest.

ReentrantReadWriteLock

  1. You can separate read and write locks using the ReadWriteLock class. Read Locks can be obtained by multiple threads, but write locks cannot.

    src/org/j6toj8/concurrency/locks/Locks_ReadWriteLock.java
    link:../../../src/org/j6toj8/concurrency/locks/Locks_ReadWriteLock.java[role=include]
    console output
    Thread-0: Got the read Lock
    Thread-2: Got the read Lock
    Thread-1: Got the read Lock
    Thread-1: Got the write Lock

    Note that all threads were able to get read lock, but only one could get write lock.

  2. If one thread already has write lock, others will not be able to get even read lock.

    src/org/j6toj8/concurrency/locks/Locks_ReadWriteLockInverted.java
    link:../../../src/org/j6toj8/concurrency/locks/Locks_ReadWriteLockInverted.java[role=include]
    console output
    Thread-0: Got the write Lock
    Thread-0: Got the read Lock

    Note that in this example the write lock is being obtained before read, so that only the first thread that was executed was able to get both locks.

References