Home  >  Article  >  Java  >  Detailed explanation with pictures and text! Summary of locks in java

Detailed explanation with pictures and text! Summary of locks in java

WBOY
WBOYforward
2022-04-15 18:16:271906browse

This article brings you relevant knowledge about java, which mainly introduces the relevant content about locks, including optimistic locks, pessimistic locks, exclusive locks, shared locks, etc., as follows Let's take a look, I hope it will be helpful to everyone.

Detailed explanation with pictures and text! Summary of locks in java

Recommended learning: "java video tutorial"

Optimistic lock and pessimistic lock

Pessimistic Lock

Pessimistic Lock Corresponds to pessimistic people in life. Pessimistic people always think about things going in the wrong direction.

To give an example in life, suppose there is only one pit in the toilet. If you lock the toilet pessimistically, you will lock the door immediately, so that other people who go to the toilet can only wait outside the door. This state is " blocked".

Back to the code world, a shared data has a pessimistic lock added. Every time a thread wants to operate this data, it will assume that other threads may also operate this data, so it will lock before each operation, so Other threads that want to operate this data cannot get the lock and can only be blocked.

Detailed explanation with pictures and text! Summary of locks in java

In the Java language, synchronized and ReentrantLock are typical pessimistic locks, and some use the synchronized keyword. Container classes such as HashTable are also applications of pessimistic locking.

Optimistic Lock

Optimistic Lock Corresponds to optimistic people in life. Optimistic people always think about things developing in a good direction.

To give an example in life, suppose there is only one pit in the toilet. Optimistic Lock believes: There are not many people in this wilderness, and no one will snatch my pit. Every time I close the door, lock it. What a waste of time, it's better not to lock it. You see, optimistic locks are born optimistic!

Back to the code world, optimistic locking will not lock when operating data. When updating, it will determine whether other threads will update the data during this period.

Detailed explanation with pictures and text! Summary of locks in java

Optimistic locking can be implemented using version number mechanism and CAS algorithm. In the Java language, the atomic class under the java.util.concurrent.atomic package is implemented using CAS optimistic locking.

Usage scenarios of the two locks

There is no better or worse between pessimistic lock and optimistic lock, and they have their own suitable scenarios.

Optimistic locking is suitable for scenarios where there are relatively few writes (relatively small conflicts). Because there is no need to lock or release locks, the overhead of locks is eliminated, thus improving throughput.

If it is a scenario with more writing and less reading, that is, the conflict is serious and competition between threads is stimulated, using optimistic lock will cause the thread to continuously retry, which may also reduce the performance. In this scenario, use pessimistic lock It's more appropriate.

Exclusive lock and shared lock

Exclusive lock

Exclusive lock means that the lock can only be held by one thread at a time have. If a thread adds an exclusive lock to the data, other threads can no longer add any type of lock to the data. A thread that obtains an exclusive lock can both read and modify data.

Detailed explanation with pictures and text! Summary of locks in java

The implementation class of Lock in the synchronized and java.util.concurrent(JUC) packages in the JDK is an exclusive lock.

Shared lock

Shared lock means that the lock can be held by multiple threads. If a thread adds a shared lock to the data, other threads can only add shared locks to the data and cannot add exclusive locks. The thread that obtains the shared lock can only read data and cannot modify the data.

Detailed explanation with pictures and text! Summary of locks in java

In JDK ReentrantReadWriteLock is a shared lock.

Mutex lock and read-write lock

Mutex lock

##Mutex lock is a conventional type of exclusive lock Implementation means that a certain resource allows only one visitor to access it at the same time, and is unique and exclusive.

Detailed explanation with pictures and text! Summary of locks in java

#Mutex lock Only one thread can own the mutex lock at a time, and other threads can only wait.

Read-write lock

Read-write lock is a specific implementation of shared lock. Read-write locks manage a set of locks, one is a read-only lock and the other is a write lock.

Read locks can be held by multiple threads at the same time when there is no write lock, and write locks are exclusive. The priority of a write lock is higher than that of a read lock. A thread that obtains a read lock must be able to see the content updated by the previously released write lock.

Read-write locks have a higher degree of concurrency than mutex locks. There is only one writing thread at a time, but multiple threads can read concurrently at the same time.

Detailed explanation with pictures and text! Summary of locks in java

A read-write lock interface is defined in the JDK: ReadWriteLock

public interface ReadWriteLock {
    /**
     * 获取读锁
     */
    Lock readLock();

    /**
     * 获取写锁
     */
    Lock writeLock();
}

ReentrantReadWriteLock implemented ReadWriteLock interface, the specific implementation will not be expanded here, and the source code will be analyzed in depth later.

Fair lock and unfair lock

Fair lock

Fair lock refers to the order in which multiple threads apply for locks Come and get the lock. It's like queuing up to buy a ticket. Those who come first buy first, and those who come later queue at the end of the queue. This is fair.

Detailed explanation with pictures and text! Summary of locks in java

In java, fair locks can be initialized through the constructor

/**
* 创建一个可重入锁,true 表示公平锁,false 表示非公平锁。默认非公平锁
*/
Lock lock = new ReentrantLock(true);

Unfair lock

Unfair lock means that the order in which multiple threads acquire locks is not in the order in which they apply for locks. It is possible that threads that apply later acquire locks before threads that apply first. In a high-concurrency environment, this may cause a priority flip. , or a starving state (a thread never gets the lock).

Detailed explanation with pictures and text! Summary of locks in java

In java, the synchronized keyword is an unfair lock, and ReentrantLock is also an unfair lock by default.

/**
* 创建一个可重入锁,true 表示公平锁,false 表示非公平锁。默认非公平锁
*/
Lock lock = new ReentrantLock(false);

Reentrant lock

Reentrant lock is also called recursive lock, which means that the same thread acquires the lock in the outer method Lock, the lock will be automatically acquired when entering the inner method.

Detailed explanation with pictures and text! Summary of locks in java

For Java ReentrantLock, its name can tell that it is a reentrant lock. For Synchronized, it is also a reentrant lock.

Knock on the blackboard: One benefit of reentrant locks is that deadlocks can be avoided to a certain extent.

Take synchronized as an example, look at the following code:

public synchronized void mehtodA() throws Exception{
 // Do some magic tings
 mehtodB();
}

public synchronized void mehtodB() throws Exception{
 // Do some magic tings
}

In the above code, methodA calls methodB. If a thread calls methodA and has acquired the lock and then calls methodB, there is no need to acquire it again. Locked, this is the characteristic of a reentrant lock. If it is not a reentrant lock, mehtodB may not be executed by the current thread, which may cause a deadlock.

Spin lock

Spin lock means that the thread is not directly suspended when the lock is not obtained, but executes a busy loop. This busy loop is the so-called of spin.

Detailed explanation with pictures and text! Summary of locks in java

#The purpose of the spin lock is to reduce the chance of the thread being suspended, because thread suspension and wake-up are also resource-consuming operations.

If the lock is occupied by another thread for a long time, the current thread will still be suspended even after spinning, and the busy loop will become a waste of system resources, which will actually reduce the overall performance. Therefore, spin locks are not suitable for concurrency situations where the lock takes a long time.

In Java, the AtomicInteger class has a spin operation. Let’s take a look at the code:

public final int getAndAddInt(Object o, long offset, int delta) {
    int v;
    do {
        v = getIntVolatile(o, offset);
    } while (!compareAndSwapInt(o, offset, v, v + delta));
    return v;
}

If the CAS operation fails, it will keep looping to obtain the current value and then try again. try.

In addition, adaptive spin locks also need to be understood.

Adaptive spin was introduced in JDK1.6. This is more intelligent. The spin time is no longer fixed. It is determined by the previous spin time on the same lock and the status of the lock owner. to decide. If the virtual machine thinks that this spin is likely to succeed again, it will take more time. If the spin rarely succeeds, it may directly omit the spin process in the future to avoid wasting processor resources.

Segmented lock

Segmented lock is a lock design, not a specific lock.

The design purpose of segmented lock is to further refine the granularity of the lock. When the operation does not need to update the entire array, only one item in the array can be locked.

Detailed explanation with pictures and text! Summary of locks in java

In the Java language, the underlying layer of CurrentHashMap uses segmentation locks. Using Segment, it can be used concurrently.

Lock upgrade (no lock|biased lock|lightweight lock|heavyweight lock)

In order to improve performance and reduce the consumption caused by acquiring and releasing locks, JDK1.6 introduced 4 lock states: No lock, biased lock, Lightweight lock and Heavyweight lock, which will change with the number of locks. The thread's contention situation gradually escalates, but cannot degrade.

Lock-free

Lock-freeThe state is actually the optimistic lock mentioned above, so I won’t go into details here.

偏向锁

Java偏向锁(Biased Locking)是指它会偏向于第一个访问锁的线程,如果在运行过程中,只有一个线程访问加锁的资源,不存在多线程竞争的情况,那么线程是不需要重复获取锁的,这种情况下,就会给线程加一个偏向锁。

偏向锁的实现是通过控制对象Mark Word的标志位来实现的,如果当前是可偏向状态,需要进一步判断对象头存储的线程 ID 是否与当前线程 ID 一致,如果一致直接进入。

轻量级锁

当线程竞争变得比较激烈时,偏向锁就会升级为轻量级锁,轻量级锁认为虽然竞争是存在的,但是理想情况下竞争的程度很低,通过自旋方式等待上一个线程释放锁。

重量级锁

如果线程并发进一步加剧,线程的自旋超过了一定次数,或者一个线程持有锁,一个线程在自旋,又来了第三个线程访问时(反正就是竞争继续加大了),轻量级锁就会膨胀为重量级锁,重量级锁会使除了此时拥有锁的线程以外的线程都阻塞。

升级到重量级锁其实就是互斥锁了,一个线程拿到锁,其余线程都会处于阻塞等待状态。

在 Java 中,synchronized 关键字内部实现原理就是锁升级的过程:无锁 --> 偏向锁 --> 轻量级锁 --> 重量级锁。这一过程在后续讲解 synchronized 关键字的原理时会详细介绍。

锁优化技术(锁粗化、锁消除)

锁粗化

锁粗化就是将多个同步块的数量减少,并将单个同步块的作用范围扩大,本质上就是将多次上锁、解锁的请求合并为一次同步请求。

举个例子,一个循环体中有一个代码同步块,每次循环都会执行加锁解锁操作。

private static final Object LOCK = new Object();

for(int i = 0;i <p>经过<code>锁粗化</code>后就变成下面这个样子了:</p><pre class="brush:php;toolbar:false"> synchronized(LOCK){
     for(int i = 0;i <p><strong>锁消除</strong></p><p><code>锁消除</code>是指虚拟机编译器在运行时检测到了共享数据没有竞争的锁,从而将这些锁进行消除。</p><p>举个例子让大家更好理解。</p><pre class="brush:php;toolbar:false">public String test(String s1, String s2){
    StringBuffer stringBuffer = new StringBuffer();
    stringBuffer.append(s1);
    stringBuffer.append(s2);
    return stringBuffer.toString();
}

上面代码中有一个 test 方法,主要作用是将字符串 s1 和字符串 s2 串联起来。

test 方法中三个变量s1, s2, stringBuffer, 它们都是局部变量,局部变量是在栈上的,栈是线程私有的,所以就算有多个线程访问 test 方法也是线程安全的。

我们都知道 StringBuffer 是线程安全的类,append 方法是同步方法,但是 test 方法本来就是线程安全的,为了提升效率,虚拟机帮我们消除了这些同步锁,这个过程就被称为锁消除

StringBuffer.class

// append 是同步方法
public synchronized StringBuffer append(String str) {
    toStringCache = null;
    super.append(str);
    return this;
}

一张图总结:

Java 并发编程的知识非常多,同时也是 Java 面试的高频考点,面试官必问的,需要学习 Java 并发编程其他知识的小伙伴可以去下载『阿里师兄总结的Java知识笔记 总共 283 页,超级详细』。

前面讲了 Java 语言中各种各种的锁,最后再通过六个问题统一总结一下:

Detailed explanation with pictures and text! Summary of locks in java

推荐学习:《java视频教程

The above is the detailed content of Detailed explanation with pictures and text! Summary of locks in java. For more information, please follow other related articles on the PHP Chinese website!

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