Concurrent programming practice 13-four kinds of locks in synchronization synchronized, ReentrantLock, ReentrantReadWriteLock, StampedLock

  1. synchronized synchronization lock
    • Synchronized is a pessimistic lock, which directly locks regions or objects. It has stable performance and can be used in most scenarios.
  2. ReentrantLock reentrant lock (Lock interface)
    • Compared with synchronized, it is more flexible and can control the position of locking and releasing
    • Condition can be used to manipulate threads and communicate between threads
    • The core class AbstractQueuedSynchronizer accommodates all blocked threads by constructing a blocking-based CLH queue, and operations on the queue are performed through Lock-Free (CAS) operations, but for threads that have acquired locks, ReentrantLock implements a biased lock. Function.
  3. ReentrantReadWriteLock reentrant read-write lock (ReadWriteLock interface)
    • Compared with ReentrantLock, for a large number of read operations, there is no lock between read and read, and only when there is a write, the lock will be added, but this lock is a pessimistic lock
    • ReentrantReadWriteLock implements the function of read-write lock
    • ReentrantReadWriteLock is the implementation class of ReadWriteLock interface. The core methods of the ReadWriteLock interface are readLock(), writeLock(). Implemented concurrent reads and mutually exclusive writes. But the read lock will block the write lock, which is a pessimistic locking strategy.
  4. StampedLock
    • Although ReentrantReadWriteLock solves the efficiency problem of a large number of reads, but because of the pessimistic lock implemented, when there are many reads, there is no lock between the read and the read, and the write operation will not be able to compete for the lock, which will cause the write thread hunger. Therefore, optimistic locking is required for reads.
    • StampedLock adds optimistic read locks, which will not exclude writes
    • When the amount of concurrency is large and the read is much larger than the write, the fastest is the StampedLock lock

There are three modes of StampedLock control lock (exclusive write, pessimistic read, optimistic read). A StampedLock state is composed of two parts: version and mode. The lock acquisition method returns a number as the ticket stamp, which is represented and controlled by the corresponding lock state. access.

StampedLock mainly uses optimistic reading. A stamp variable is used to detect whether there is a read-write conflict. A stamp check is added to each optimistic reading. When there is a write operation, the write operation will change the state of the stamp, which will cause the optimistic read to fail, and the optimistic read lock will be upgraded to a pessimistic read lock

package com.sound.daytd5;

import java.util.concurrent.locks.StampedLock;

/**
 * @author: ZouTai
 * @date: 2018/4/17
 * @description:
 */
public class StampedLockDemo {
    private int balance;
    private final StampedLock stampedLock = new StampedLock();


    /**
     * 1、悲观写
     * writeLock():典型的cas操作,如果STATE等于s,设置写锁位为1(s+WBIT)。
     * acquireWrite跟acquireRead逻辑类似,先自旋尝试、加入等待队列、直至最终Unsafe.park()挂起线程。
      */
    public void write(int i) {
        long stamp = stampedLock.writeLock();
        balance += i;
        stampedLock.unlockWrite(stamp);
    }

    /**
     * 2、悲观读
     * 乐观锁失败后锁升级为readLock():尝试state+1,用于统计读线程的数量,
     * 如果失败,进入acquireRead()进行自旋,通过CAS获取锁。
     * 如果自旋失败,入CLH队列,然后再自旋,
     * 如果成功获得读锁,激活cowait队列中的读线程Unsafe.unpark(),
     * 最终依然失败,Unsafe().park()挂起当前线程。
     */
    public void read() {
        long stamp = stampedLock.readLock();
        int value = balance;
        stampedLock.unlockRead(stamp);
    }

    /**重点:!!!
     * 3、乐观读:当读取远远大于写入时,使用乐观锁
     * tryOptimisticRead():如果当前没有写锁占用,返回state(后7位清0,即清0读线程数),如果有写锁,返回0,即失败。
     */
    public void optimisticRead() {
        long stamp = stampedLock.tryOptimisticRead();
        int value = balance;
        // 校验这个戳是否有效validate():比较当前stamp和发生乐观锁得到的stamp比较,不一致则失败。
        if(!stampedLock.validate(stamp)) {
            long readStamp = stampedLock.readLock();
            value = balance;
            stamp = readStamp;
        }
        stampedLock.unlockRead(stamp);
    }

    /**重点:!
     * 4、判断条件之后,再写
     * 存在读取和写入两个操作
     */
    public void conditionReadWrite(int state){
        // 首先读取
        long stamp = stampedLock.readLock();
        while (balance > 100){
            long writeStamp = stampedLock.tryConvertToWriteLock(stamp);
            // 步骤:a
            if(writeStamp!=0) {
                balance += state;
                stamp = writeStamp;
                break;
            } else {
                // 转换失败
                stampedLock.unlockRead(stamp);
                //显式直接进行写锁 然后再通过循环再试,回到 步骤:a
                stamp = stampedLock.writeLock();
            }
        }
    }

}

Performance Comparison of Four Locks in
Synchronization The four kinds of locks in synchronization Synchronized, ReentrantLock, ReentrantReadWriteLock, StampedLock
synchronization locks refer to English documents

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326316684&siteId=291194637