What is the Lock

It is ajava.util.concurrent.locksA class under the package

As usual, use the official documentation to learn more about what Lock is and how to use it

  • Lock provides a wider range of locking operations than using synchronized methods and blocks. Is the way to lock more flexible. They allow for a more flexible structure, may have completely different attributes, and may support multiple associated Condition objects.

  • In general, locks provide exclusive access to shared resources: only one thread at a time can acquire the lock, and all access to the shared resource needs to acquire the lock first. However, some locks may allow parallel access to shared resources, such as ReadWriteLock’s ReadLock.

    • As for parallel access to shared resources, for example, in the case of multiple threads, some threads are read operations, some threads are write operations, for the read operation of the shared resources can be accessed in parallel, rather than the need to limit one thread at a time

  • The use of synchronized methods or statements provides access to implicit Monitor locks associated with each object, but forces all lock acquisition and release to occur in a block structure: When multiple locks are acquired (locks on multiple objects acquired by a thread), they must be released in reverse order, and all locks must be released within the same lexical scope (block of statements) from which they were acquired.

  • Synchronized is convenient, but has a downside: locks are acquired and released sequentially, automatically, and in the same scope.

  • The implementation of the Lock interface allows locks to be acquired and released in different scopes (scopes) and multiple locks to be acquired and released in any order, eliminating automatic release of synchronized locks and becoming manual.

  • When locking and unlocking occur in different scopes, care must be taken to ensure that all code executed while holding the lock is protected by a try-finally or try-catch to ensure that the lock is released if necessary.

  • The Lock implementation provides a non-blocking attempt to obtain the Lock(tryLock()), an attempt to obtain the Lock that can be interrupted (lockInterruptibly, And tryLock() attempts to acquire the lock to provide more functionality than synchronized methods and statements. TryLock (long, TimeUnit) attempts to acquire the lock over time without being blocked. Synchronized causes threads to block.

    • In terms of blocking and non-blocking, (blocking and non-blocking is whether a thread can be suspended and do nothing)

  • The Lock class can also provide behavior and semantics that are completely different from implicit monitor (the synchronized keyword actually allows threads to acquire the monitor, but is not visible at the code level) locks, such as guaranteed sorting, non-reentrant use, or deadlock detection. If the implementation provides such specialized semantics, then the implementation must document those semantics.

  • Note that Lock instances are just ordinary objects that can themselves be used as targets in synchronized statements. The monitor Lock that acquires a Lock instance has no specific relationship to any Lock method that calls that instance. It is recommended not to use Lock instances in this way to avoid confusion, except in their own implementation.

  • Unless otherwise stated, passing a null value for any argument will result in a NullPointerException being thrown.

  • All Lock implementations must enforce the same memory synchronization semantics provided by the built-in monitor Lock

    • Java memory model
  • The three forms of lock acquisition (interruptible, non-interruptible, and timed) may differ in their performance characteristics, sort assurance, or other implementation qualities. In addition, it may not be possible to interrupt ongoing Lock acquisition in a given Lock class. Therefore, the implementation does not need to define exactly the same guarantees or semantics for all three forms of lock acquisition, nor does it need to support the interruption of ongoing lock acquisition. An implementation is needed to clearly document the semantics and guarantees provided by each locking method. It must also comply with the interrupt semantics defined in this interface to support locking acquired interrupts: entirely or only on method entries.

  • Because interrupts usually mean cancellations, and interrupt checks are usually rare, implementations can tend to respond to interrupts rather than normal method returns. This is true even if it can be proved that the interrupt occurred after another action may have unblocked the thread. The implementation should document this behavior.

Then take a look at the methods in the Lock interface

void lock();

  • To obtain the lock.
  • If the lock is not available, the current thread is disabled for thread scheduling purposes and sleeps until the lock is acquired.
  • Implementation note: Lock implementationIt may be possible to detect an incorrect use of the lock, such as a call that causes a deadlock, and in this casemayAn (unchecked) exception is thrown. The Lock implementationMust beMark the exception type.

void lockInterruptibly() throws InterruptedException;

  • The lock is acquired unless the current thread is interrupted.

    • Thread the interruptDepending on the program itself, the resulting thread dies, waits for a new task, or continues to the next step.

  • If lock is available, the lock is acquired and returned immediately.

  • If the lock is not available, the current thread will be disabled for thread scheduling purposes and put to sleep until one of two things happens:

    • The lock is acquired by the current thread. or
    • Other threads interrupt the current thread and support the interrupt to acquire the lock.
  • If the current thread:

    • Set the middle off state when entering this method; or
    • Interrupts while acquiring the lock, which supports interrupting the acquisition of the lock and then throws InterruptedException and clears the interrupted status of the current thread.
  • Note when implementing:

    • In some implementations, it may not be possible to interrupt the ability to acquire locks, and if possible, it may be an expensive operation. Programmers should be aware that this may be the case. In this case, the implementation should record.
    • Implementations can be more responsive to interrupts than normal method returns.
    • The Lock implementation may be able to detect the wrong use of the Lock, such as a call that causes a deadlock, and may throw (unchecked) exceptions in that case. The Lock implementation must log the situation and mark the exception type.
  • Throw InterruptedException

    • If the current thread is interrupted while acquiring the lock (and supports locking interrupt)

boolean tryLock();

  • The lock is acquired only if it is idle at the time of invocation.
  • If available, the lock is acquired and a value of true is returned immediately. This method returns false immediately if the lock is not available.
  • A typical use of this method is:
Lock lock = ... ;if (lock.tryLock()) {
   try {
     // Manipulate protected State
   } finally{ lock.unlock(); }}else {
   // Perform alternative actions
 }
Copy the code
  • This usage ensures that the lock is unlocked when it is acquired and that no attempt is made to unlock it if it is not.
  • The return value:
    • True if the lock is acquired, false otherwise

boolean tryLock(long time, TimeUnit unit) throws InterruptedException;

  • If idle during the given wait time and the current thread is not interrupted, the lock is acquired.
  • This method returns true immediately if the lock is available. If the lock is not available, the current thread will be disabled for thread scheduling purposes and put to sleep until one of three conditions occurs:
    • The lock is acquired by the current thread. or
    • Other threads interrupt the current thread and support interrupt lock acquisition (interrupt lock acquisition is supported); or
    • After the specified waiting time
  • Returns true if the lock was acquired.
  • If the current thread:
    • When entering this method, set it to the interrupted state; or
    • Interrupt to acquire lock, support to interrupt to acquire lock, and then throwInterruptedExceptionAnd clears the interrupted state of the current thread.
  • Returns false if the specified wait time has elapsed.
  • If the time is less than or equal to zero, the method does not wait at all.
  • Note when implementing:
    • In some implementations, it may not be possible to interrupt the ability to acquire locks, and if possible, it may be an expensive operation. Programmers should be aware that this may be the case. In this case, the implementation should record.
    • Implementations can tend to respond to interrupts (responding to interrupt requests) rather than normal method returns, or to report timeouts.
    • LockThe implementation may be able to detect incorrect uses of locks, such as calls that cause deadlocks, and may throw (unchecked) exceptions in such cases. theLockImplementations must record conditions and exception types.

Parameter: time – Maximum time to wait for a lock unit – Time unit of time for the argument (enumeration value) Returned value: true if the lock was acquired and false if the wait elapsed before the lock was acquired Throw: InterruptedException – If the current thread is interrupted while acquiring the lock (and supports breaking the lock)

void unlock();

  • Releases the lock.
  • Note when implementing:
    • LockImplementations typically impose restrictions on which thread can release the lock (usually only the lock holder can release it) and may throw (unchecked) exceptions if the restrictions are violated. theLockThe implementation must log any restrictions and exception types.

Condition newCondition();

  • Returns a new bound to this Lock instanceConditionInstance.
  • Waiting for theConditionPreviously, the current thread must hold the lock. callCondition.await()Will be before waitingAutomatic release lockAnd waiting for the returnReacquire lock.
  • Implementation considerations
    • ConditionThe exact operation of the instance depends onLockImplementation, and must be documented by the implementation.

Return value: the new Condition of the Lock instance instance throw: UnsupportedOperationException – if the actualization of the Lock does not support conditions

summary

Key differences between Lock and synchronized

1. Locks are acquired manually by the developer through program code and by the JVM (without developer intervention) 2. Specific implementation: the former is implemented through Java code, the latter is implemented through the UNDERLYING JVM (no developer concern) 3. Locks can be released: the former must be released manually ina finally block using unlock(), while the latter is released by the JvM (without developer concern) 4. Specific types of locks: the former provides a variety of locks, such as fair locks, non-fair locks, the latter and the former provide reentrant locks

Fair and unfair locks and other implementation details are available in theReentrantLockThe relevant chapters are introduced