13. ReentrantLock、ReentrantReadWriteLock、StampedLock讲解

13.1 Interview questions about locks
● Do you know what locks exist in Java
● Tell me about the locks you have used. What is the problem of lock hunger?
● Is there a faster lock than the read-write lock
● StampedLock know? (postmark lock/bill lock)
● ReentrantReadWriteLock has a lock downgrade mechanism, do you know?

13.2 Briefly talk about ReentrantReadWriteLock
13.2.1 What is it? ● Description of read
-write lock ○ A resource can be accessed by multiple read threads, or by one write thread, but read- write threads
cannot exist at the same time. Postmark lock ● Significance and characteristics of read-write lock ○ It only allows reading and reading to coexist, while reading and writing and writing and writing are still mutually exclusive. In most actual scenarios, there is no mutual exclusion relationship between "read/read" threads, only "read/read" The operations between "write" threads or "write/write" threads require mutual exclusion, so ReentrantReadWriteLock is introduced. ○ A ReentrantReadWriteLock can only have one write lock at the same time but can have multiple read locks, but it cannot exist at the same time. , that is, the resource can be accessed by multiple read operations, or by a single write operation, but not both at the same time. ○ Read-write locks have higher performance only in the context of more reads and fewer writes.





13.2.2 Features
● Reentrant
● Both reading and writing
● Conclusion: one body with two sides, read and write are mutually exclusive, read and read are shared, and other threads cannot obtain write locks when the read is not completed ●
Lock downgrade:
○ Downgrade write lock to read lock ------>Follow the sequence of acquiring write locks, acquiring read locks, and releasing write locks. Write locks can be downgraded to read locks.
If a thread holds a write lock, it will still You can continue to acquire read locks. This is the downgrade of the write lock, downgraded to a read lock.
○ If the write lock is released, it will be completely converted to a read lock.
○ If there are threads reading, the write thread cannot acquire the write lock. It is a pessimistic lock strategy.

insert image description here
13.3 Interview question: Is there a lock faster than the read-write lock?
13.4 What is StampedLock
13.4.1?
StampedLock is a new read-write lock in JDK1.8. It is also an optimized stamp for the read-write lock ReentrantReadWriteLock in JDK1.5. The stamp
represents the state of the lock. When the stamp returns zero, it means that the thread failed to acquire the lock, and when releasing the lock or converting the lock, the originally acquired stamp value must be passed in.
13.4.2 It is caused by the starvation problem
● Lock starvation problem:
○ ReentrantReadWriteLock realizes read-write separation, but once there are many read operations, it becomes more difficult to obtain write locks, so it may always exist Read locks, write locks cannot be acquired.
● How to solve the lock starvation problem:
○ Using the "fair" strategy can alleviate this problem to a certain extent
○ Using the "fair" strategy is at the expense of system throughput
○ Optimistic read lock method of the StampedLock class—>Optimistically acquire the lock, and other threads will not be blocked when they try to acquire the write lock. After acquiring the optimistic read lock, the result needs to be verified. 13.4.3 StampedLock
Features
All lock methods return a postage stamp. If the stamp is zero, it means failure, and all other methods indicate success. All lock
release methods require a postage stamp. The stamp must be consistent with the stamp obtained when the lock is successfully acquired
. StampedLock is not reentrant Yes, dangerous (if a thread already holds a write lock, it will cause a deadlock if it acquires the write lock)

● StampedLock has three access modes:
○ Reading (read mode pessimistic): the function is similar to the read lock of ReentrantReadWriteLock
○ Writing (write mode): the function is similar to the write lock of ReentrantReadWriteLock
○ Optimistic reading (optimistic read mode): no lock mechanism, similar With the optimistic lock in the database, it supports concurrent reading and writing. It is optimistic that no one will modify it when reading. If it is modified, it will be upgraded to a pessimistic reading mode.

● One sentence: Write locks are also allowed to intervene during the reading process

13.4.5 Optimistic Read Mode Code Demonstration
● Traditional Read-Write Lock Mode----Write locks cannot be obtained when reading


public class StampedLockDemo {
    
    
    static int number = 37;
    static StampedLock stampedLock = new StampedLock();

    public void write() {
    
    
        long stamp = stampedLock.writeLock();
        System.out.println(Thread.currentThread().getName() + "\t" + "写线程准备修改");
        try {
    
    
            number = number + 13;
        } finally {
    
    
            stampedLock.unlockWrite(stamp);
        }
        System.out.println(Thread.currentThread().getName() + "\t" + "写线程结束修改");
    }

    public void read() {
    
    
        long stamp = stampedLock.readLock();
        System.out.println(Thread.currentThread().getName() + "\t" + " come in readLock codeBlock");
        for (int i = 0; i < 4; i++) {
    
    
            try {
    
    
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "\t" + " 正在读取中");
        }
        try {
    
    
            int result = number;
            System.out.println(Thread.currentThread().getName() + "\t" + "获得成员变量值result: " + result);
            System.out.println("写线程没有修改成功,读锁时候写锁无法介入,传统的读写互斥");
        } finally {
    
    
            stampedLock.unlockRead(stamp);
        }

    }

    public static void main(String[] args) {
    
    
        StampedLockDemo resource = new StampedLockDemo();
        new Thread(() -> {
    
    
            resource.read();
        }, "readThread").start();

        try {
    
    
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }

        new Thread(() -> {
    
    
            System.out.println(Thread.currentThread().getName()+"\t"+" come in");
            resource.write();
        }, "writeThread").start();
    }
}
/**
 * readThread	 come in readLock codeBlock
 * readThread	 正在读取中
 * writeThread	 come in
 * readThread	 正在读取中
 * readThread	 正在读取中
 * readThread	 正在读取中
 * readThread	获得成员变量值result: 37
 * 写线程没有修改成功,读锁时候写锁无法介入,传统的读写互斥
 * writeThread	写线程准备修改
 * writeThread	写线程结束修改
 */

Optimistic read mode----write locks are also allowed to intervene during the read process


public class StampedLockDemo {
    
    
    static int number = 37;
    static StampedLock stampedLock = new StampedLock();

    public void write() {
    
    
        long stamp = stampedLock.writeLock();
        System.out.println(Thread.currentThread().getName() + "\t" + "写线程准备修改");
        try {
    
    
            number = number + 13;
        } finally {
    
    
            stampedLock.unlockWrite(stamp);
        }
        System.out.println(Thread.currentThread().getName() + "\t" + "写线程结束修改");
    }

    public void read() {
    
    
        long stamp = stampedLock.tryOptimisticRead();

        int result = number;

        System.out.println("4秒前 stampedLock.validate方法值(true 无修改 false有修改)" + "\t" + stampedLock.validate(stamp));
        for (int i = 0; i < 4; i++) {
    
    
            try {
    
    
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "\t" + " 正在读取...." + i + "秒后" + "stampedLock.validate方法值(true 无修改 false有修改)" + "\t" + stampedLock.validate(stamp));
        }
        if (!stampedLock.validate(stamp)) {
    
    
            System.out.println("有人修改----------有写操作");
            stamp = stampedLock.readLock();
            try {
    
    
                System.out.println("从乐观读升级为悲观读");
                result = number;
                System.out.println("重新悲观读后result:" + result);
            } finally {
    
    
                stampedLock.unlockRead(stamp);
            }
        }
        System.out.println(Thread.currentThread().getName() + "\t" + "finally value: " + result);

    }


    public static void main(String[] args) {
    
    
        StampedLockDemo resource = new StampedLockDemo();
        new Thread(() -> {
    
    
            resource.read();
        }, "readThread").start();

        try {
    
    
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }

        new Thread(() -> {
    
    
            System.out.println(Thread.currentThread().getName() + "\t" + " come in");
            resource.write();
        }, "writeThread").start();
    }
}
/**
 * 4秒前 stampedLock.validate方法值(true 无修改 false有修改)	true
 * readThread	 正在读取....0秒后stampedLock.validate方法值(true 无修改 false有修改)	true
 * readThread	 正在读取....1秒后stampedLock.validate方法值(true 无修改 false有修改)	true
 * writeThread	 come in
 * writeThread	写线程准备修改
 * writeThread	写线程结束修改
 * readThread	 正在读取....2秒后stampedLock.validate方法值(true 无修改 false有修改)	false
 * readThread	 正在读取....3秒后stampedLock.validate方法值(true 无修改 false有修改)	false
 * 有人修改----------有写操作
 * 从乐观读升级为悲观读
 * 重新悲观读后result:50
 * readThread	finally value: 50
 */

13.4.6 Disadvantages of StampedLock
● StampedLock does not support reentrancy and does not start with Re
● StampedLock’s pessimistic read lock and write lock do not support condition variables, which is also important
● When using StampedLock, do not call interrupt operations, that is, do not call interrupt() method

Guess you like

Origin blog.csdn.net/weixin_45817985/article/details/131180938
Recommended