[Interview] Java Concurrency (3)

0, topic outline

Three, keywords

3.1、wait、sleep、notify、notifyAll

1、sleep和wait的区别,sleep会不会释放锁
 - 追问1:sleep会不会释放锁?

2、notify和notifyAll的区别
 - 追问1:为什么notify()可能会导致死锁,而notifyAll()则不会?

3.2、Synchronized、Volatile、ReentrantLock

1、可重入锁的可重入性是什么意思,哪些是可重入锁?

2synchronized和ReentrantLock有什么区别呢?【第15讲】(*33synchronized底层如何实现?(*4)什么是锁的升级、降级?【第16讲】
 - 追问1:Synchronized对于非静态方法和静态方法加锁的区别是什么?
 - 追问2:Java 使用Synchronized关键字有什么隐患?
 - 追问3:Synchronized和lock的区别(*34、ReentrantLock底层实现原理(*25、Java读写锁,
 - 追问1:为什么并发读要加锁?

6、Volatile产生背景、作用(*2- 追问1:Volatile怎么保证可见性?
 - 追问2:Volatile怎么保证有序性?
 - 追问3:应用场景?变量不断加一,是否能够并发加正确
 - 追问4:底层如何实现?

7、Volatile和Synchronized的区别

Three, keywords

3.1、wait、sleep、notify、notifyAll

1. The difference between sleep and wait, sleep will release the lock

  • How to use
    sleep is a method of the Thread class, which has nothing to do with locks.
    wait is the top class method of Object, used together with notify and notifyAll for the lock mechanism.

  • Regarding the exception
    sleep() must catch the exception, wait() does not need to catch the exception.

  • CPU occupies
    sleep() to release CPU resources, but does not release lock resources.
    wait() releases CPU resources and also releases lock resources.

  • The essential difference
    sleep() is the running state control of threads, and wait() is the communication between threads.

Follow-up 1: Will sleep release the lock?

[The outer package has synchronized] No, it just releases the CPU resources, but the lock resources are not released.

2. The difference between notify and notifyAll

notifyAll will all wait for pool threads into the lock pool to the opportunity to compete lock;
the Notify will randomly select a thread pool to wait for the lock to enter the pool to compete lock opportunity.

补充:

1、锁池
假设线程A已经拥有了某个对象ObjectA(不是类)的锁,而其他线程B,C想要调用这个对象的某个sychronized方法(或者块)。
线程必须先获得该对象锁的拥有权,才能进入对象的的synchronized方法。
但是ObjectA的锁正被线程A拥有,所以线程B、C会被阻塞,进入一个地方【对象锁池】去等待锁释放。

简要理解,锁池就是 线程 获取锁进行等待的地方。

2、等待池
假设线程A调用了某个对象ObjectA的wait方法,线程A就会释放对象的锁;同时线程A就进入ObjectA的等待池,进入等待池中的线程不会去竞争ObjectA的锁

重点:锁池和等待池都是针对对象。
Follow-up 1: Why notify() may cause deadlock, but notifyAll() does not?

notifyAll will all threads moved by the pool waiting for lock pool to participate lock compete successfully proceed, if unsuccessful, to stay in the pool waiting for the lock after the lock is released to compete again; and notify only wake up one thread, it may lead to death lock.

3.2、Synchronized、Volatile、ReentrantLock

The Java Memory Model (JMM) acts on the data synchronization process between the working memory (local memory) and the main memory. It specifies how and when to do data synchronization, as shown in the figure below.
4

1. What does the reentrancy of reentrant locks mean, and which ones are reentrant locks?

Reentrancy: It can be reused correctly.
Reentrant locks: synchronized and ReentrantLock.

(待消化确认)可重入锁:自己可以再次获取自己的内部锁。比如,一个线程获得了某个对象的锁,此时这个对象锁还没有释放,当其再次想要获取这个对象的锁时,还可以再获取的;如果不可锁重入的话,就会造成死锁;同一个线程每次获取锁,锁的计数器都自增1,所以要等到锁的计数器下降为0时,才能最终释放锁。

2. What is the difference between synchronized and ReentrantLock? [Lecture 15] (*3)

[1] Same: Both are reentrant locks and both provide mutual exclusion semantics. When a thread has acquired the current lock, other threads trying to acquire can only wait or block there.

[2] Difference

  • synchronized depends on the JVM, and ReentrantLock depends on the API .
  • ReentrantLock adds three functions: waiting can be interrupted, fair lock can be realized, selective notification can be realized (lock can be bound to multiple conditions) .

[3] Performance: It cannot be generalized. The early performance of synchronized is quite different, and subsequent versions have more improvements, and may perform better than ReentrantLock in low-competition scenarios.

补充:
0、Lock接口比synchronized锁定操作更广泛、更灵活。可以具有完全不同的属性,并且可以支持多个关联的Condition条件对象。
1、ReentrantLock锁比synchronized更具扩展性,灵活高效,额外具有嗅探锁定、多路分支通知等功能;
2、Lock接口提供比synchronized更广泛与灵活的操作;
3、Condition给ReentrantLock提供了等待/通知,而且相比synchronized中函数(wait,notify,notifyAll)更加灵活性,还可以实现多路通知功能,

3. How to realize synchronized bottom layer? (*4) What are lock upgrades and downgrades? [Lecture 16]

The synchronized code block is realized by a pair of monitorenter/monitorexit instructions, and the Monitor object is the basic realization unit of synchronization.

Before Java 6, the implementation of Monitor relied entirely on the mutual exclusion lock inside the operating system. Because of the need to switch from user mode to kernel mode, the synchronization operation was an undifferentiated heavyweight operation.

In the modern (Oracle) JDK, the JVM has made drastic improvements to this, providing three different Monitor implementations, which is often referred to as three different locks: Biased Locking, Lightweight Locking and The heavyweight lock greatly improves its performance.

The so-called lock upgrade and downgrade are the mechanism by which the JVM optimizes the synchronized operation. When the JVM detects different competition conditions, it will automatically switch to the appropriate lock implementation. This switching is the lock upgrade or downgrade.

When there is no competition, the skew lock will be used by default. JVM will use the CAS operation (compare and swap) to set the thread ID in the Mark Word part of the object header to indicate that the object is biased toward the current thread, so no real mutex lock is involved. This assumption is based on the fact that in many application scenarios, most objects will be locked by at most one thread during their life cycle. Using skewed locks can reduce competition-free overhead.

If another thread tries to lock an object that has been skewed, the JVM needs to revoke the skewed lock and switch to a lightweight lock implementation. Lightweight locks rely on CAS operation Mark Word to try to acquire the lock. If the retry succeeds, ordinary lightweight locks are used; otherwise, they are further upgraded to heavyweight locks.

I have noticed some opinions that Java will not perform lock downgrades. In fact, as far as I know, lock downgrade does happen. When the JVM enters the safe point (SafePoint), it will check whether there is an idle Monitor and then try to downgrade.

Follow-up 1: What is the difference between Synchronized's locking of non-static methods and static methods?

1) Modifying a non-static method is actually locking the object calling the method , commonly known as "object lock".
2) Modification of static methods is actually to lock the object of this type , commonly known as "class lock".

Synchronous non-static methods actually lock the instance object of the current object. Only one thread can access the synchronization method of the instance at the same time, but for the synchronization method of multiple instances, the access to the synchronization method between different instances is not affected by synchronization (synchronized synchronization failure).

Synchronizing static methods, the lock is a class object rather than an instance object, so it can be understood that the lock for the static method is a global lock, and synchronization is also a global synchronization.

synchronized modified object Non-static method Static method
case 1 Two synchronization methods for the same object to access the object in two threads respectively Use the class to directly call two different synchronization methods
result Mutually exclusive Mutually exclusive
reason Object lock, when the object calls a synchronized, other synchronization methods will not release the lock until the execution is complete, and then execute. Class (.class) lock, there is only one class object, and only one space is used. It can be understood that there are N rooms and a lock, so the rooms (synchronization method) must be mutually exclusive.
case 2 Different objects call the same synchronization method in two threads Use a static object of a class to call a static method or a non-static method
result Not mutually exclusive Mutually exclusive
reason Object lock, here are two objects. The methods can be executed concurrently and will not be mutually exclusive. The image says that when each thread calls a method, an object will be new, then two spaces and two keys will appear. Because it is an object call, ibid
case 3 - An object calls a static synchronization method and a non-static synchronization method in two threads respectively
result - Mutually exclusive
reason - Although it is an object call, the lock types of the two methods are different. The static method called is called by the class object, that is, the two methods do not generate the same object lock, so they will not be mutually exclusive and will be executed concurrently.
Follow-up 2: What are the hidden dangers of using Synchronized keywords in Java?
  • 1) The lock timeout time cannot be set;
  • 2) The lock cannot be released by code;
  • 3) It is easy to cause deadlock.
Follow-up 3: The difference between Synchronized and lock (*3)
Lock type synchronized lock
performance When resource competition is not fierce, synchronize performance is better. When resource competition is fierce, lock performance is better
Lock mechanism Implemented at the JVM level, the system monitors whether the lock is released or not Is JDK code implementation, you need to manually release resources
Programming synchronized is more concise and can be used in methods/code blocks Lock has many functions and is more flexible. The disadvantage is that it can only be written in the code and cannot be modified directly.
延伸:synchronize会根据锁竞争情况,从偏向锁-->轻量级锁-->重量级锁升级,lock可以采用非阻塞的方式获取锁。

4. The underlying implementation principle of ReentrantLock (*2)

4
ReentrantLock implements fair locks and unfair locks by rewriting the two methods of lock acquisition and lock release.

First, ReentrantLock inherits from the parent class Lock, and then there are 3 internal classes, the Sync internal class inherits from AQS, and the other two internal classes inherit from Sync. These two classes are used for fair lock and unfair lock.

Through the methods tryAcquire and tryRelease rewritten by Sync, we can know that ReentrantLock implements the exclusive mode of AQS, that is, the exclusive lock, which is a pessimistic lock.
...

5. Java read-write lock,

Unlike traditional locks, the rule of read-write locks is that reads can be shared, but only one can be written. In summary, read and read are not mutually exclusive, read and write are mutually exclusive, write and write are mutually exclusive, and the general exclusive lock is: read Reading is mutually exclusive, reading and writing are mutually exclusive, and writing is mutually exclusive. In the scene, reading is often far greater than writing. The read-write lock is a mechanism created for this optimization. Note that reading is far greater than writing. In general, the low efficiency of exclusive locks comes from fierce competition for critical sections under high concurrency, which leads to thread context switching. Therefore, when the concurrency is not very high, the read-write lock may not be as efficient as the exclusive lock due to the additional maintenance of the state of the read lock. Therefore, it needs to be selected according to the actual situation.

Follow-up 1: Why is the concurrent reading locked?

A read lock is an intermediate value that prevents reads and writes.

6. Volatile produces background and functions (*2)

Background: The multi-level cache between the processor and the memory improves the execution speed of the processor, but also introduces the problem of inconsistent cache data. However, multiple threads access the same variable, and one thread modifies the variable value, which may cause inconsistent reading by other threads.

Function: Volatile is a variable modifier, which can only be used to modify variables, and cannot modify methods and code blocks.
Usage: simple, just use volatile to modify variables that may be accessed by multiple threads at the same time.

补充:
1、缓存一致性背景:多处理器下,为了保证各个处理器的缓存是一致的,就会实现缓存一致性协议
2、缓存一致性协议:每个处理器通过嗅探在总线上传播的数据来检查自己缓存的值是不是过期了,当处理器发现自己缓存行对应的内存地址被修改,就会将当前处理器的缓存行设置成无效状态,当处理器要对这个数据进行修改操作的时候,会强制重新从系统内存里把数据读到处理器缓存里。
Follow-up 1: How does Volatile guarantee visibility?

Visibility: When multiple threads access the same variable, one thread modifies the variable value, and other threads can immediately see the modified value.

Volatile can synchronize the modified variable to the main memory immediately after being modified, and the variable is refreshed from the main memory before each use . Therefore, variable visibility can be guaranteed during multi-threaded operation.

If a variable is modified by volatile, its value will be forced to be flushed into the main memory after each data change. The caches of other processors will also load the value of this variable from the main memory into their own caches because they comply with the cache coherency protocol.

Follow-up 2: How does Volatile ensure orderliness?

Volatile can prohibit instruction rearrangement, ensuring that the code is executed in strict order. This ensures orderliness.

原子性:一个或一组操作要么都做,要么都不做。volatile不能保证原子性。
Follow-up 3: Application scenarios? Variables keep increasing by one, can they be added concurrently?

Application scenario: The value of a variable does not depend on the current value when it is updated, and the variable will not form an immutable condition with others.

例如:
1、可用volatile
1-1)只有一个线程执行写操作,其它线程都是读操作;
1-2)只有简单读写操作,如set i=2, get i。

2、不能用volatile
i++就不行,它有一次读一次写
Follow-up 4: How to realize the bottom layer?

Memory barrier...

7. The difference between Volatile and Synchronized

Keyword volatile synchronized
Use level Can only modify variables Modifiable variables, methods, and classes
Element guarantee Only guarantee visibility and order Ensure visibility, order, and atomicity
block Will not cause thread blocking maybe
Compiler optimization Tag variables will not be optimized Tag variables can be optimized
  • Essential contrast
  • The essence of volatile is to tell the JVM that the value of the current variable in the register (working memory) is uncertain and needs to be read from the main memory;
  • Synchronized is to lock the current variable, only the current thread can access the variable, other threads are blocked.

Four, reference

1. The difference between sleep() and wait()
in Java 2. The difference between sleep and wait in Java multithreading is summarized very well.
3. The difference between sleep, yield, wait and join (Ali)
4. The difference between notify and notifyAll (producer consumer case)
5. The difference between notify and notifyAll
6. What is the difference between notify and notifyAll in java?
7. What is the difference between notify and notifyAll in java?
8. Deep understanding of reentrancy
9. Summary of Synchronized synchronous static methods and non-static methods
10. Talk about the difference between synchronized and ReentrantLock
11. Summary of ReenTrantLock reentrant lock (difference from synchronized)
12. Two synchronization methods of java , The difference between Synchronized and ReentrantLock
13, Java synchronized multi-threaded synchronization problem detailed explanation
14, Interviewer: talk about multi-threaded concurrency problems
15, in-depth analysis of Synchronized principle (Ali interview questions)
16,The difference between Synchronized and Lock
17. In- depth understanding of the realization principle
of ReentrantLock 18. ReentrantLock realization principle
19. Java-the realization principle of read-write lock
20. What is the use of read lock? Why is reading locked?
21, Java concurrent programming principle and actual combat 18: read-write lock
22, in-depth understanding of the volatile keyword in Java
23, a volatile with the interviewer for half an hour
24, the difference between volatile and synchronized

Guess you like

Origin blog.csdn.net/HeavenDan/article/details/112984259