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

What is the principle of synchronized

2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

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

This article introduces the relevant knowledge of "what is the principle of synchronized". In the operation of actual cases, many people will encounter such a dilemma. Then let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

(1) Overview

In multithreaded program execution, it is possible that multiple threads will access a shared and variable resource at the same time, because the execution of the thread is uncontrollable, so some ways must be used to control the access to the resource. this way is "locking".

We call those resources that may be operated by multiple threads at the same time as critical resources. The purpose of locking is to make these critical resources accessible to only one thread at a time.

(2) introduction of CAS

CAS:compare and swap, compare and exchange. Using the CAS operation, you can update a value by multithreading without a lock. The specific operations of CAS are as follows:

When you want to update a value, first get the current value E, calculate the updated result value V (not updated first), when you want to update this value, compare whether the value is still equal to E, if equal, update E to V, if not, then redo the above operation.

For example, if there is no lock, the operation is thread unsafe. Assuming that the initial value of I is 0, the CAS operation will first get the original value of 0, and then calculate the updated value 1. Before updating, compare whether this value is still equal to 0. If it is equal to 0, update E to 1. If not equal to 0, it means that a thread has updated it. Get the value of E = 1 again and continue to execute.

ABA problem

The CAS operation may have an ABA problem, and the ABA problem, the value E that we are going to compare, changes from 0 to 1 to 0 after the operation of multiple threads. At this time, although the E value is equal to that before the update, it has been updated.

The solution to the ABA problem

Add a version number to the E value, get the version number every time you want to get the data, and increment the version number after each update, so that you can know whether it has been modified through the version number even if the value is equal.

Java uses CAS operations in many places, such as some classes of Atomic:

AtomicInteger i=new AtomicInteger ()

In the AtomicInteger method, you can see a class called Unsafe. When you enter this class, you can see several operation methods of CAS.

(3) the storage layout of objects in memory

To learn synchronized, you must first understand the memory layout, or memory structure, of Java objects.

An object is divided into object headers, instance data, and populating them.

The object header Header occupies 12 bytes: Mark Word occupies 8 bytes, and the type pointer class pointer takes 4 bytes (compressed by default, 8 bytes if compression is not enabled)

The instance object has different sizes according to the actual storage, and it equals 0 when the object is empty.

Padding indicates alignment, and the corresponding number of bytes is added when the bytes occupied by memory are not divisible by 8.

Taking Object o=new Object () as an example, we first import a jol dependency, and we can see the specific memory layout through jol.

Org.openjdk.jol jol-core 0.9

Run the following code:

Public static void main (String [] args) {Object o=new Object (); System.out.println (ClassLayout.parseInstance (o). ToPrintable ());}

According to the observation, OFFSET represents the starting point of the offset, and SIZE represents the bytes occupied. The first two lines are Mark Word with a total of 8 bytes, and the third line is class pointer with 4 bytes. In this case, the object is empty, the instance object is equal to 0, and finally the padding is completed, with a total of 16 bytes.

(3) synchronized

Synchronized ensures that only one thread can execute a method or a block of code at a time, and synchronized stores the lock information in the MarkWord of the object header.

The role of synchronized on non-static methods is to lock the method, while the role of synchronized on static methods is to lock the current class.

In earlier versions of jdk, synchronized was a heavyweight lock that kept threads safe but inefficient. Later, synchronized was optimized to have a lock upgrade process:

Unlocked (new)-- > bias lock-- > lightweight lock (spin lock)-- > heavyweight lock

The lock information is recorded through 8 bytes or 64 bits in the MarkWord. Some people call a spin lock unlocked, because the optional operation does not lock an object, so you just have to understand what it means.

3.1 details of the lock upgrade process:

When you add a synchronized lock to an object, it is equivalent to a biased lock.

When a thread requests, change the ID of the object MarkWord to the current thread pointer ID (JavaThread), allowing only this one thread to request the object.

When other threads also request, upgrade the lock to a lightweight lock. Each thread generates LockRecord in its own thread stack and uses the CAS spin operation to change the request object MarkWordID to its own LockRecord. The successful thread requests to the object, and the unsuccessful object continues to spin.

If the competition intensifies, when a thread spins more than a certain number of times (after JDK1.6, the number of spins is controlled by JVM itself), the lightweight lock is upgraded to a heavy lock, and the thread hangs, enters the waiting queue, and waits for the operating system to schedule.

3.2 implementation of locked bytecode

After the synchronized keyword is compiled into bytecode, it is translated into two instructions: monitorenter and monitorexit. Monitorenter is executed when the synchronous code block is entered, and monitorexit is executed after the synchronous code block is executed.

(IV) Lock elimination

In some cases, if JVM believes that a lock is not needed, the lock is automatically eliminated, such as the following code:

Public void add (String a) string b) {StringBuffer sb=new StringBuffer (); sb.append (a) .append (b);}

StringBuffer is thread-safe, but stringbuffer is a resource that cannot be shared in this add method, so locking will only increase performance consumption, and JVM will eliminate locks within StringBuffer.

(5) Lock coarsening

In some cases, when JVM detects that a series of operations are constantly locking the same object, it will add the lock to the outside of the series of operations, such as:

StringBuffer sb=new StringBuffer (); while (I

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