Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to understand the use and underlying principle of Java Synchronized

2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

How to understand the use and underlying principles of Java Synchronized, in view of this problem, this article introduces the corresponding analysis and solutions in detail, hoping to help more partners who want to solve this problem to find a more simple and feasible method.

Thread safety issues 1. Critical resources

In multithreaded programming, it is possible for multiple threads to access the same shared and variable resource at the same time, which we call critical resources; such resources may be: objects, variables, files, and so on.

Sharing: resources can be accessed by multiple threads simultaneously

Mutable: resources can be modified during their lifecycle

2. Thread safety issues

When multiple threads access an object at the same time, if you do not need to consider the scheduling and alternating execution of these threads in the runtime environment, there is no need for additional synchronization, or any other coordinated operation on the caller, the behavior of calling this object can get the correct result, then the object is called thread-safe, otherwise it is non-thread-safe.

3. How to solve the thread safety problem

Mutually exclusive synchronization (Mutual Exclusion & Synchronization) is one of the most common and most important means to guarantee the correctness of concurrency. Synchronization refers to ensuring that shared data is used by only one (or some, when semaphores) threads at a time when multiple threads access shared data concurrently. Mutex is a means to achieve synchronization, and critical section (Critical Section), mutex (Mutex) and semaphore (Semaphore) are common mutual exclusion methods.

In Java, the most basic means of mutex synchronization is the synchronized keyword. In addition, the Lock interface in JUC has been introduced from JDK1.5, in which ReentrantLock is often used, which will be introduced later.

Introduction to the use of synchronized

Synchronized is built into JVM and is reentrant, and it can be used in three ways: adding to static-decorated static methods, adding to normal methods, and synchronizing code blocks.

Add to the static method (public synchronized static void test ()), locking the Class object of the current class

Add to the instance method (public synchronized void test ()) to lock the current object

Synchronized synchronization code block (synchronized (object) {.}), locking objects in parentheses after synchronized

From the above, we can see that synchronized locks are all objects.

Third, synchronized implementation principle 1. Synchronized underlying instructions: monitorenter and monitorexit

Synchronized is based on JVM built-in lock implementation, through the internal object Object Monitor (monitor lock), based on entry and exit Monitor object implementation method and code block synchronization, the implementation of monitor lock depends on the underlying operating system Mutex lock (mutex lock) implementation, it is a heavyweight lock with low performance. Of course, JVM built-in locks have been greatly optimized after 1.5, such as lock coarsening (Lock Coarsening), lock elimination (Lock Elimination), lightweight locks (Lightweight Locking), biased locks (Biased Locking), adaptive spin (Adaptive Spinning) and other technologies to reduce the overhead of lock operations, and the concurrency performance of built-in locks is basically the same as that of Lock.

Note: Object Monitor (monitor lock) is only used if the synchronized lock is upgraded to a heavyweight lock.

After the synchronized keyword is compiled into bytecode, it is translated into monitorenter and monitorexit instructions at the beginning and end of the synchronous block logic code, respectively.

Public class TestSynchronized {private Object obj = new Object (); public void testLock () {synchronized (obj) {System.out.println ("lock acquired");}

We disassemble the class file of the above code through javap-c TestSynchronized.class, and we can see the following: we see two instructions monitorenter and monitorexit, but monitorexit appears twice for the following reasons:

The first monitorexit instruction is a sign that the synchronous code block releases the lock normally.

If Exception or Error appears in the synchronization code block, the second monitorexit instruction is called to ensure that the lock is released

Public void testLock (); Code: 0: aload_0 1: getfield # 3 / / Field obj:Ljava/lang/Object; 4: dup 5: astore_1 6: monitorenter 7: getstatic # 4 / / Field java/lang/System.out:Ljava/io/PrintStream 10: ldc # 5 / / String / invokevirtual # 6 / / Method java/io/PrintStream.println: (Ljava/lang/String ) V 15: aload_1 16: monitorexit 17: goto 25 20: astore_2 21: aload_1 22: monitorexit 23: aload_2 24: athrow 25: return Exception table: from to target type 7 17 20 any 20 23 20 any2, Object Monitor (Monitor Lock) mechanism

As mentioned above, Object Monitor (monitor locks) is only used when synchronized locks are upgraded to heavyweight locks. Let's take a look at the implementation mechanism of Object Monitor. If you look at the OpenJDK source code, you can see that Object Monitor is implemented in C++ language. Open the JDK source directory "jdk\ hotspot\ src\ share\ vm\ runtime" to see objectMonitor.hpp. This is the implementation of the monitor lock. The code is intercepted as follows:

ObjectMonitor () {_ header = NULL; / / an image header _ count = 0; / / record the number of locks, the number of lock reentrants used _ waiters = 0, / / the current number of thread _ recursions in wait state = 0; / / record the number of lock reentrants _ object = NULL; _ owner = 0 / / pointing to the thread holding the ObjectMonitor object _ WaitSet = NULL; / / the thread in the wait state will be added to _ WaitSet _ WaitSetLock = 0; _ Responsible = NULL; _ succ = NULL; _ cxq = NULL; FreeNext = NULL; _ EntryList = NULL / / Threads waiting for locked block will be added to the list _ SpinFreq = 0; _ SpinClock = 0; OwnerIsThread = 0; _ previous_owner_tid = 0;}

Several of the more important fields are:

_ header object header. As mentioned earlier, objectMonitor will not be used until the synchronized lock is upgraded to a heavyweight lock. In this case, the Mark word of the object header will have a pointer to the heavyweight lock Monitor.

The number of times the count thread acquired the lock, adding 1 to each lock.

_ waiters how many thread are currently in the wait state

_ number of reentrants of recursions lock

_ owner points to the address of the thread that holds the ObjectMonitor object.

_ WaitSet stores the queue of threads that call the wait method and enter the waiting state.

_ EntryList threads waiting for locked block will be added to the list

The locking and unlocking process of ObjectMonitor is shown in the figure below. There are two queues in ObjectMonitor, _ WaitSet and _ EntryList, which are used to store the list of ObjectWaiter objects (each thread waiting for the lock is encapsulated into an ObjectWaiter object). The whole monitor runs as follows:

_ owner points to the thread that holds the ObjectMonitor object. When multiple threads access a piece of synchronous code at the same time, it will first enter the _ EntryList collection.

When the thread gets the monitor of the object and enters the _ Owner area and sets the owner variable in monitor to the current thread, the counter count in monitor increases 1

If the thread that has acquired the lock calls the wait () method, it restores the currently held monitor,owner variable to null,count minus 1, while the thread enters the WaitSet collection waiting to be woken up.

If the current thread finishes executing, it also releases the monitor (lock) and resets the value of the variable so that other threads enter and acquire the monitor (lock).

The answers to the questions about how to understand the use of Java Synchronized and the underlying principles are shared here. I hope the above content can be of some help to you. If you still have a lot of doubts to be solved, you can follow the industry information channel to learn more about it.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report