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

Example Analysis of visibility and atomicity of java

2025-02-25 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >

Share

Shulou(Shulou.com)05/31 Report--

This article mainly explains "java visibility and atomicity example analysis". The content of the article is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn "java visibility and atomicity example analysis".

Brief introduction

Many variables are defined in the java class, including class variables and instance variables. These variables will encounter some visibility and atomicity problems in the process of access. Here let's take a closer look at how to avoid these problems.

Visibility of immutable objects

Immutable objects are objects that cannot be modified after initialization, so is it true that immutable objects are introduced into the class, and all modifications to immutable objects are immediately visible to all threads?

In fact, immutable objects can only guarantee the security of object use in a multithreaded environment, but not the visibility of objects.

To discuss variability first, let's consider the following example:

Public final class ImmutableObject {private final int age;public ImmutableObject (int age) {this.age=age;}}

We define an ImmutableObject object, class is final, and the only field in it is final. So the ImmutableObject cannot be changed after initialization.

Then we define a class to get and set this ImmutableObject:

Public class ObjectWithNothing {private ImmutableObject refObject;public ImmutableObject getImmutableObject () {return refObject;} public void setImmutableObject (int age) {this.refObject=new ImmutableObject (age);}}

In the above example, we defined a reference refObject to the immutable object, and then defined the get and set methods.

Note that although the class ImmutableObject itself is immutable, our reference to the object refObject is mutable. This means that we can call the setImmutableObject method multiple times.

Let's talk about visibility again.

In the above example, in a multithreaded environment, does each setImmutableObject cause getImmutableObject to return a new value?

The answer is no.

When the source code is compiled, the order of the instructions generated in the compiler is not exactly the same as the order of the source code. The processor may execute instructions out of order or in parallel (this reordering is allowed in JVM as long as the final execution result of the program is consistent with that in a strict serial environment). And the processor also has a local cache, and when the results are stored in the local cache, other threads cannot see the results. In addition, the order in which caches are committed to main memory can also be changed.

How to solve it?

The easiest way to solve the visibility is to add the volatile keyword, which uses the happens-before rules of the java memory model to ensure that volatile's variable changes are visible to all threads.

Public class ObjectWithVolatile {private volatile ImmutableObject refObject;public ImmutableObject getImmutableObject () {return refObject;} public void setImmutableObject (int age) {this.refObject=new ImmutableObject (age);}}

In addition, the same effect can be achieved by using the locking mechanism:

Public class ObjectWithSync {private ImmutableObject refObject;public synchronized ImmutableObject getImmutableObject () {return refObject;} public synchronized void setImmutableObject (int age) {this.refObject=new ImmutableObject (age);}}

Finally, we can also use atomic classes to achieve the same effect:

Public class ObjectWithAtomic {private final AtomicReference refObject= new AtomicReference (); public ImmutableObject getImmutableObject () {return refObject.get ();} public void setImmutableObject (int age) {refObject.set (new ImmutableObject (age));}} guarantee the atomicity of the composite operation of shared variables

If it is a shared object, then we need to consider atomicity in a multithreaded environment. If it is a compound operation on shared variables, such as + +,-- * =, / =,% =, + =,-=, =, > =, ^ =, etc., it appears to be a statement, but it is actually a collection of multiple statements.

We need to consider the security under multithreading.

Consider the following example:

Public class CompoundOper1 {private int iposit public int increase () {ifficient return I;}}

In the example, we accumulate the int I. But + + actually consists of three operations:

Read the value of I from memory and write it to the CPU register.

Change the I value + 1 in the CPU register

Write the value back to I in memory.

There is no problem in a single-threaded environment, but in a multithreaded environment, a problem may occur because it is not an atomic operation.

There are many solutions, the first of which is to use the synchronized keyword

Public synchronized int increaseSync () {return I;}

The second is to use lock:

Private final ReentrantLock reentrantLock=new ReentrantLock (); public int increaseWithLock () {try {reentrantLock.lock (); finally {reentrantLock.unlock ();}}

The third is to use the Atomic atomic class:

Private AtomicInteger atomicInteger=new AtomicInteger (0); public int increaseWithAtomic () {return atomicInteger.incrementAndGet ();} guarantee the atomicity of multiple Atomic atomic class operations

If a method uses operations of multiple atomic classes, although a single atomic operation is atomic, it may not be combined.

Let's look at an example:

Public class CompoundAtomic {private AtomicInteger atomicInteger1=new AtomicInteger (0); private AtomicInteger atomicInteger2=new AtomicInteger (0); public void update () {atomicInteger1.set (20); atomicInteger2.set (10);} public int get () {return atomicInteger1.get () + atomicInteger2.get ();}}

In the above example, we define two AtomicInteger and operate on two AtomicInteger in the update and get operations, respectively.

Although AtomicInteger is atomic, it is not when two different AtomicInteger are merged. Problems may be encountered in the process of multithreading operations.

Similarly, we can use synchronization mechanisms or locks to ensure data consistency.

Ensure the atomicity of the method call chain

If we are going to create an instance of an object, the instance of the object is created through a chained call. Then we need to ensure the atomicity of chained calls.

Consider the following example:

Public class ChainedMethod {private int age=0;private String name= "; private String adress="; public ChainedMethod setAdress (String adress) {this.adress = adress;return this;} public ChainedMethod setAge (int age) {this.age = age;return this;} public ChainedMethod setName (String name) {this.name = name;return this;}}

For a very simple object, we define three properties, and each time set returns a reference to this.

Let's take a look at how to call in a multithreaded environment:

ChainedMethod chainedMethod= new ChainedMethod (); Thread T1 = new Thread (()-> chainedMethod.setAge (1). SetAdress ("www.flydean.com1"). SetName ("name1"); t1.start (); Thread T2 = new Thread (()-> chainedMethod.setAge (2). SetAdress ("www.flydean.com2"). SetName ("name2"); t2.start ()

Because in a multithreaded environment, the above set method may be confusing.

How to solve it? We can first create a local copy, which is thread-safe because it is locally accessed, and finally copy it to the newly created instance object.

The main code looks like this:

Public class ChainedMethodWithBuilder {private int age=0;private String name= "; private String adress="; public ChainedMethodWithBuilder (Builder builder) {this.adress=builder.adress;this.age=builder.age;this.name=builder.name;} public static class Builder {private int age=0;private String name="; private String adress="; public static Builder newInstance () {return new Builder ();} private Builder () {} public Builder setName (String name) {this.name= name;return this;} public Builder setAge (int age) {this.age= age Return this;} public Builder setAdress (String adress) {this.adress = adress;return this;} public ChainedMethodWithBuilder build () {return new ChainedMethodWithBuilder (this);}}

Let's see how to call:

Final ChainedMethodWithBuilder [] builder = new ChainedMethodWithBuilder [1]; Thread T1 = new Thread (()-> {builder [0] = ChainedMethodWithBuilder.Builder.newInstance () .setAge (1). SetAdress ("www.flydean.com1"). SetName ("name1") .build (); t1.start () Thread T2 = new Thread (()-> {builder [0] = ChainedMethodWithBuilder.Builder.newInstance () .setAge (1). SetAdress ("www.flydean.com1"). SetName ("name1") .build (); t2.start ()

Because the variables used in the lambda expression must be final or final equivalent, we need to build an array of final.

Read and write the value of 64bits

In java, 64bits's long and double are treated as two 32bits.

So one 64bits operation is divided into two 32bits operations. Which leads to the problem of atomicity.

Consider the following code:

Public class LongUsage {private long I = 0 th public void setLong (long I) {this.i=i;} public void printLong () {System.out.println ("I =" + I);}}

Because the reading and writing of long is divided into two parts, there may be problems if the methods of setLong and printLong are called multiple times in a multithreaded environment.

The solution is simple: define the long or double variable as volatile.

Private volatile long i = 0; thank you for reading, the above is the content of "java visibility and atomicity example analysis". After the study of this article, I believe you have a deeper understanding of the problem of java visibility and atomicity example analysis, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!

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

Servers

Wechat

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

12
Report