ReentrantLock lock related methods

catalogue

ReentrantLock lock

Implementation class of Lock interface

ReentrantLock

The effect is the same as the synchronized keyword

ReentrantLock method

public String toString()

Returns a string identifying this lock and its lock status. The states in parentheses include the string "Unlocked" or the string "Locked by", followed by the name of the owning thread.

public int getWaitQueueLength(Condition condition)

Returns an estimate of the number of threads waiting under a given condition associated with the lock. Please note that since timeouts and interruptions may occur at any time, this estimate is only used as the upper limit of the actual number of attendants. This method is intended for monitoring system status, not for synchronous control.

public boolean hasWaiters(Condition condition)

Query whether any thread is waiting for the given condition associated with this lock. Please note that since timeouts and interrupts may occur at any time, the real return does not guarantee that future signals will wake up any thread. This method is mainly designed to monitor the system status.

public final boolean hasQueuedThread(Thread thread)

Query whether the given thread is waiting to acquire this lock. Note that since cancellation can occur at any time, the actual return does not guarantee that the thread will always acquire this lock. This method is mainly designed to monitor the system status.

public final int getQueueLength()

Returns an estimate of the number of threads waiting to acquire this lock. This value is only an estimate, because the number of threads may change dynamically when the method traverses the internal data structure. This method is intended for monitoring system status, not for synchronous control.

public final boolean hasQueuedThreads()

Query whether any thread is waiting to acquire this lock. Note that since cancellation can occur at any time, the actual return does not guarantee that any other thread will get the lock. This method is mainly designed to monitor the system status.

public final boolean isFair()

Returns true if the fairness of this lock is set to true

public boolean isLocked()

Query whether this lock is held by any thread. This method is intended for monitoring system status, not for synchronous control.

public int getHoldCount()

Query the reserved number of this lock by the current thread.
The thread has a lock for each locking action, but the unlocking action does not match.

public boolean isHeldByCurrentThread()

Query whether the lock is held by the current thread.
Similar to thread with built-in monitor lock Holdslock (object) method, which is usually used for debugging and testing.

public ReentrantLock()

Create an instance of ReentrantLock. This is equivalent to using ReentrantLock(false).

public ReentrantLock(boolean fair)

Create a ReentrantLock instance using the given fairness policy. (true indicates fair lock Policy)

ReentrantLockTest test

Thread for testing

Thread t1 = new Thread(() -> {
            for (int i = 0; i < 2; i++) {
                try {
                    lock.lock();
                    System.out.println("t1 Acquire lock:lock.lock()");
                    lock.lock();//Each cycle repeats the acquisition of the lock for 2 times
                    System.out.println("t1 Acquire lock:lock.lock()");
                } finally {
                    System.out.println("t1 Release lock:lock.unlock()");
                    lock.unlock();//The lock is released only once per cycle
                }
            }
            System.out.println("t1 Current pair lock Acquisition times of:" + lock.getHoldCount());
        });

        Thread t2 = new Thread(() -> {
            try {
                System.out.println("t2 thread  lock.lock()");
                lock.lock();
                System.out.println("t2 Acquired lock: lock");
            } finally {
                lock.unlock();
            }
        });

        Thread t3 = new Thread(() -> {
            try {
                System.out.println("t3 use trylock()Attempt to acquire lock");
                if (lock.tryLock())
                    System.out.println("t3 Thread acquired lock");
                else
                    System.out.println("t3 Failed to acquire lock");

            } finally {
                if (lock.isHeldByCurrentThread())
                    lock.unlock();
                else
                    System.out.println("t3 No lock acquired, no execution required unlock()");
            }
        });

        Thread t4 = new Thread(() -> {
            try {
                System.out.println("t4 use lockInterruptibly()Attempt to acquire lock");
                lock.lockInterruptibly();
                System.out.println("t4 Lock acquired");
            } catch (InterruptedException e) {
                System.out.println("t4 Waiting lock Interrupted on release");
                e.printStackTrace();
            } finally {
                if (lock.isHeldByCurrentThread()) {
                    lock.unlock();
                } else {
                    System.out.println("t4 No lock acquired, no execution required unlock()");
                }
            }
        });

t1 test

System.out.println("\nt1 Thread start");
        t1.start();
        Thread.sleep(100);

Release the reentry lock correctly

t1 thread has not released the lock at this time
The mechanism of ReentrantLock is:

If a thread acquires this lock
You can repeat the acquisition several times later
But the same number of releases are required
The lock can be released correctly

Get the current number of reentries

t1 thread acquires lock 4 times in total
Release the lock twice
The remaining 2 acquisitions are not released

Outside the thread loop, the reentry times of thread t1 to lock are obtained through lock.getHoldCount()

t1t2 test

        System.out.println("\nt1 Thread start");
        t1.start();
        Thread.sleep(100);
        System.out.println(lock.isLocked());

        System.out.println("\nt2 Thread start");
        t2.start();
        Thread.sleep(100);

Use the islocked() method to detect the lock state

If the lock has been acquired by a thread
The islocked method returns true
Otherwise, it returns false

Because thread t1 did not release the reentry lock correctly, t2 did not acquire the lock

t1t3 test

System.out.println("\nt1 Thread start");
        t1.start();
        Thread.sleep(100);
System.out.println("\nt3 Thread start");
        t3.start();
        Thread.sleep(100);

Use the trylock method to attempt to acquire a lock

trylock attempts to acquire a lock
Returns true if the acquisition is successful
If the acquisition fails, it returns false and will not block to wait for the lock to be released

Use the isHeldByCurrentThread method to detect whether the current thread holds a lock

Returns true if the current thread holds this lock
Returns false if the current thread does not hold a lock

Call the unlock method when the lock is not held

If the thread uses this lock without acquiring it, the unlock method is used
An illegalMonitorStateException will be thrown

t3 middle
Use isHeldByCurrentThread detection before releasing the lock
Avoid releasing the lock when it is not held

t1t4 test

        System.out.println("\nt1 Thread start");
        t1.start();
        Thread.sleep(100);
        System.out.println("\nt4 Thread start");
        t4.start();
        Thread.sleep(100);
        t4.interruput();

Use lockInterruptbly() to attempt to acquire a lock

The same effect as lock()
When the acquisition fails, the block waits for the lock to be released, but this thread can respond to interrupts during the blocking period

Interrupt the thread blocked by lockInterruptbly()

When a thread is blocked by lockInterruptbly()
If an interrupt request is received
interruptedException will be thrown

The effect is the same as the interrupt request received during sleep wait
Exceptions can be caught for interrupt handling

t1t2t3t4 test

System.out.println("\nt1 Thread start");
        t1.start();
        Thread.sleep(100);

        System.out.println("\nt2 Thread start");
        t2.start();
        Thread.sleep(100);

        System.out.println("\nt3 Thread start");
        t3.start();
        Thread.sleep(100);

        System.out.println("\nt4 Thread start");
        t4.start();
        Thread.sleep(100);

        System.out.println("\nlock Detection method of lock:");
        System.out.println("Is there a thread waiting lock Lock:"+lock.hasQueuedThreads());
        System.out.println("How many threads are waiting lock Lock:"+lock.getQueueLength());
        System.out.println("t2 Whether the thread is waiting lock Lock:"+lock.hasQueuedThread(t2));
        System.out.println("lock Whether it is a fair lock:"+lock.isFair());

Use the hasQueuedThreads method to detect whether there are threads waiting for this lock

If it returns true, it indicates that a thread is waiting for this lock
Otherwise, it returns false

Use the getQueueLength method to detect the number of threads waiting for this lock

The integer returned represents the number of threads waiting for this lock
Here, T2 and T4 threads are waiting for locks
The t3 thread did not obtain the lock using trylock(). The code that has executed the else path exits without blocking and waits for the lock to be released

Use the hasQueuedThread method to detect whether the specified thread is waiting for this lock

If it returns true, it means that the thread is waiting for the lock to be released
If false is returned, it means that the thread is not waiting for the lock

Use isFair to detect whether this lock is fair

If true is returned, it means that the lock is fair
If false is returned, it means that the lock is not a fair lock

Fair lock, that is, the thread requesting to acquire the lock obtains the lock in the order of request
Unfair lock, that is, all threads requesting to acquire this lock compete randomly

Tags: Java jvm Algorithm Multithreading

Posted by wxflint on Sun, 04 Sep 2022 22:34:19 +0300