Home  >  Article  >  Java  >  How to use StampedLock lock in Java concurrent programming

How to use StampedLock lock in Java concurrent programming

WBOY
WBOYforward
2023-04-24 08:01:061328browse

StampedLock:

StampedLock is a new lock added to the JDK8 version in the concurrent package. This lock provides three modes of read and write control. When calling When the series of functions that acquire the lock return a long variable, we call it a stamp. This stamp represents the status of the lock. The try series of functions that acquire locks will return a stamp value of 0 when the lock acquisition fails. When calling the methods of releasing locks and converting locks, you need to pass in the stamp value returned when acquiring the lock.

The three read and write mode locks provided by StampedLock are as follows:

  • Write lock witeLock: is a row It locks or exclusively locks. Only one thread can acquire the lock at a time. When a thread acquires the lock, other threads requesting read locks and write locks must wait. This is similar to the write lock of ReentrantReadWriteLock (the difference is that the write lock here The lock is a non-reentrant lock): The lock can only be acquired when no thread currently holds a read lock or write lock. After successfully requesting the lock, a stamp variable will be returned to represent the version of the lock. When the lock is released, the unlockWrite method needs to be called and the stamp parameter of the lock date passed. And it provides a non-blocking tryWriteLock method.

  • Pessimistic read lock readLock: is a shared lock. When no thread acquires an exclusive write lock, multiple threads can acquire the lock at the same time. If a thread already holds the write lock, other threads' requests to acquire the read lock will be blocked, which is similar to the read lock of ReentrantReadWriteLock (the difference is that the read lock here is a non-reentrant lock). The pessimism mentioned here means that before specifically operating the data, it will pessimistically believe that other threads may modify the data it operates, so it needs to lock the data first. This is a consideration when reading less and writing more. After successfully requesting the lock, a stamp variable will be returned to represent the version of the lock. When the lock is released, the unlockRead method needs to be called and the stamp parameter passed. And it provides a non-blocking tryReadLock method.

  • Optimistic read lock tryOptimisticRead: It is relative to the pessimistic lock. The lock status is not set through CAS before operating the data, only bit operations are used. test. If no thread currently holds the write lock, a non-zero stamp version information is simply returned. After obtaining the stamp, you need to call the validate method to verify whether the stamp is no longer available before specifically operating the data, that is, whether there are other threads holding the write lock between the time when tryOptimisticRead returns the stamp and the current time. If so, validate will Return 0 otherwise you can use the stamp version of the lock to operate on the data. Since tryOptimisticRead does not use CAS to set the lock status, there is no need to explicitly release the lock. One feature of this lock is that it is suitable for scenarios where there are many reads and few writes. Because acquiring the read lock only uses bit operations for verification and does not involve CAS operations, the efficiency will be much higher. However, at the same time, since no real lock is used, data consistency is ensured. It is necessary to copy the variables to be operated to the method stack, and when operating the data, other writing threads may have modified the data, and what we operate is the data in the method stack, which is a snapshot, so the most returned is not the latest data, but consistency is still guaranteed.

StampedLock also supports mutual conversion of these three locks under certain conditions. For example, long tryConvertToWriteLock(long stamp) expects to upgrade the lock marked by stamp to a write lock.

This function will return a valid stamp in the following situations (that is, Successful promotion of write lock):

  • #The current lock is already in write lock mode.

  • The previous lock is in read lock mode, and no other thread is in read lock mode

  • It is currently in optimistic read mode, and the current write lock is available

In addition, StampedLock 's read and write locks are non-reentrant locks, so you should not call operations that will acquire the lock after acquiring the lock but before releasing the lock. To avoid causing the calling thread to be blocked. When multiple threads try to acquire read locks and write locks at the same time, there are no certain rules for who acquires the lock first. It is completely done on a best-effort basis and is random. And the lock does not directly implement the Lock or ReadWriteLock interface, but maintains a two-way blocking queue internally.

The following is an example of managing two-dimensional points provided in JDK8 to understand the concepts introduced above.

package LockSupportTest;

import com.sun.org.apache.bcel.internal.generic.BREAKPOINT;

import java.util.concurrent.locks.StampedLock;

public class Point_Class {
    private double x,y;
    private final StampedLock sl = new StampedLock();
    
    void move(double deltaX, double deltaY) {
        long stamp = sl.writeLock();
        try {
            x += deltaX;
            y += deltaY;
        } finally {
            sl.unlockWrite(stamp);
        }
    }
    
    double distanceFromOrin() {
        long stamp = sl.tryOptimisticRead();
        double currentX = x, currentY = y;
        if (!sl.validate(stamp)) {
            stamp = sl.readLock();
            try {
                currentX = x;
                currentY = y;
            } finally {
                sl.unlockRead(stamp);
            }
        }
        return Math.sqrt(currentX*currentX + currentY*currentY);
    }
    
    void moveIfAtOrigin(double newX, double newY) {
        long stamp = sl.readLock();
        try {
            while (x == 0.0 && y == 0.0) {
                long ws = sl.tryConvertToWriteLock(stamp);
                if (ws != 0L) {
                    stamp = ws;
                    x = newX;
                    y = newY;
                    break;
                } else {
                    sl.unlockRead(stamp);
                    stamp = sl.writeLock();
                }
            }
        } finally {
                    sl.unlock(stamp);
                }
            }
}

In the above code, the Point class has two member variables (x, y) used to represent the two-dimensional coordinates of a point, and three methods for operating coordinate variables. In addition, a StampedLock object is instantiated to ensure the atomicity of the operation.

The above is the detailed content of How to use StampedLock lock in Java concurrent programming. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete