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 are the steps of Java concurrent code design

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

Share

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

This article mainly introduces "what are the steps of Java concurrent code design". In daily operation, I believe that many people have doubts about the steps of Java concurrent code design. The editor consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful to answer the doubts of "what are the steps of Java concurrent code design?" Next, please follow the editor to study!

Release and escape

Before that, let's take a look at the concepts of release and escape.

Publishing refers to the use of objects outside the current scope, such as methods that pass references to objects to other classes, return their references in a method, and so on.

In many cases, we need to ensure that internal objects are not published, and publishing some internal state may break the encapsulation, so that users can change their state at will, thus destroying thread safety.

In some cases, we need to publish some internal objects, and if we need thread safety, we need proper synchronization.

This is called escaping when an object is released when it should not be published.

Public class Escape {private List users = Lists.newArrayList (); public List getUsers () {return users;} public void setUsers (List users) {this.users = users;}}

GetUsers has escaped its scope, and this private variable has been released because any caller can modify the array.

At the same time, the reference to the User object is also published indirectly when the users is released.

Public class OuterEscape {private String str = "Outer's string"; public class Inner {public void write () {System.out.println (OuterEscape.this.str);}} public static void main (String [] args) {OuterEscape out = new OuterEscape (); OuterEscape.Inner in = out.new Inner (); in.write ();}

A reference to the outer class that created the inner class is saved in the inner class, so the private properties and methods of the outer class that created the inner class can be used in the inner class.

Public class ConstructorEscape {private Thread t; public ConstructorEscape () {System.out.println (this); t = new Thread () {public void run () {System.out.println (ConstructorEscape.this);}}; t.start () } public static void main (String [] args) {ConstructorEscape a = new ConstructorEscape ();}}

The this reference is shared by thread t, so the publication of thread t will lead to the publication of ConstructorEscape objects, which will cause ConstructorEscape objects to escape because the ConstructorEscape objects have not yet been constructed when they are published.

Summarize the steps to release securely

Find out all the variables that make up the state of the object

Find out the invariance condition of constrained state variables.

Establish a concurrent access strategy for object state

Thread closure

The idea of thread closure is very simple, since thread safety problems are caused by multi-thread access to shared variables, then if we can avoid manipulating shared variables and each thread accesses its own variables, there will be no thread safety problems, which is the easiest way to achieve thread safety.

Through thread control escape rules can help you determine whether the access to certain resources in the code is thread-safe, if the creation, use, and destruction of a resource are all done in the same thread and will never get out of the control of the thread, then the use of the resource is thread-safe.

Resources can be objects, arrays, files, database connections, sockets, and so on. You don't need to destroy the object actively in Java, so "destroy" means that there are no more references to the object. Even if the object itself is thread-safe, if the object contains other resources (files, database connections), the entire application may no longer be thread-safe. For example, two threads create their own database connections, and each connection itself is thread-safe, but the same database they connect to may not be thread-safe.

Let's take a look at several implementations of thread closure:

Stack closure

Stack closure is a special case of thread closure, in which objects can only be accessed through local variables, and local variables are stored in the thread's own stack. That is, local variables are never shared by multiple threads. Therefore, local variables of the underlying type are thread-safe.

The local reference to the object is different from the local variable of the underlying type. Although the reference itself is not shared, the object referred to by the reference is not stored in the thread's stack. All objects are stored in the shared heap. If an object created in a method does not escape from that method, it is thread-safe. In fact, even if you pass this object as a parameter to other methods, it is still thread-safe as long as it is not available to other threads.

Public void someMethod () {LocalObject localObject = new LocalObject (); localObject.callMethod (); method2 (localObject);} public void method2 (LocalObject localObject) {localObject.setValue ("value");}

As above, the LocalObject object is not returned by the method, nor is it passed to an object outside the someMethod () method. Each thread executing someMethod () creates its own LocalObject object and assigns a value to the localObject reference. Therefore, the LocalObject here is thread-safe. In fact, the entire someMethod () is thread-safe. Even when LocalObject is passed as an argument to other methods of the same class or methods of other classes, it is still thread safe. Of course, if LocalObject is passed to another thread in some way, it is no longer thread-safe.

Program control thread closure

Thread closure through program implementation, that is, we cannot use language features to close objects to specific threads. this makes this approach less reliable assuming that we guarantee that only one thread can write to a shared object, then the "read-modify-write" of this object will not be subject to a normal condition under any circumstances. If we decorate the object with volatile, we can ensure the visibility of the object. Any thread can read the object, but only one thread can write to it. In this way, its security is properly ensured through volatile modification alone, which is more appropriate but slightly more complex to implement than using synchoronized modification directly.

Program control thread closure, this is not a specific technology, but a design idea, from the design to deal with the state of an object code into a thread, so as to avoid the problem of thread safety.

ThreadLocal

The ThreadLocal mechanism is essentially program-controlled thread closure, but the Java itself helps to deal with it. Take a look at Java's Thread class and ThreadLocal class:

The Thread thread class maintains an instance variable of ThreadLocalMap

ThreadLocalMap is a Map structure.

The set method of ThreadLocal takes the current thread, gets the threadLocalMap object of the current thread, and then takes the ThreadLocal object as key, and puts the value to be put as value into Map

The get method of ThreadLocal takes the current thread, gets the threadLocalMap object of the current thread, and then takes the ThreadLocal object as the key and gets the corresponding value

Public class Thread implements Runnable {ThreadLocal.ThreadLocalMap threadLocals = null;} public class ThreadLocal {public T get () {Thread t = Thread.currentThread (); ThreadLocalMap map = getMap (t); if (map! = null) {ThreadLocalMap.Entry e = map.getEntry (this); if (e! = null) return (T) e.value;} return setInitialValue () } ThreadLocalMap getMap (Thread t) {return t.threadLocals;} public void set (T value) {Thread t = Thread.currentThread (); ThreadLocalMap map = getMap (t); if (map! = null) map.set (this, value); else createMap (t, value);}}

The design of ThreadLocal is simple: set up an internal Map for the thread object so that you can put some data. JVM ensures from the bottom that Thread objects will not see each other's data.

The premise of using ThreadLocal is to save a separate object for each ThreadLocal. The object cannot be shared among multiple ThreadLocal, otherwise the object is also thread-unsafe.

ThreadLocal memory leak

ThreadLocalMap uses the weak reference of ThreadLocal as the key. If a ThreadLocal does not have an external strong reference to reference it, the ThreadLocal is bound to be recycled when the system GC. In this way, Entry with key as null will appear in the ThreadLocalMap, and there will be no way to access these value with Entry whose key is null. If the current thread does not finish any longer, These Entry value with key null will always have a strong reference chain: Thread Ref-> Thread-> ThreaLocalMap-> Entry-> value can never be recycled, resulting in memory leaks.

In fact, this situation has been taken into account in the design of ThreadLocalMap, and some protective measures have been added: in ThreadLocal's get (), set (), remove (), all value in thread ThreadLocalMap whose key is null will be cleared.

So every time you finish using ThreadLocal, you call its remove () method, and you can avoid this problem by clearing the data.

Immutable object

An object is called an immutable object if it cannot be modified after creation. In concurrent programming, a generally accepted principle is to use immutable objects as much as possible to create simple and reliable code

Immutable objects are particularly useful in concurrent programming. Since it cannot be modified after creation, memory consistency errors caused by manipulating shared variables will not occur.

But programmers are usually not keen to use immutable objects because they worry about the cost of creating new objects each time. In fact, this cost is often overestimated and offset by some efficiency gains from the use of immutable objects

Let's first look at an example of using synchronization to solve thread safety.

Public class SynchronizedRGB {/ / Values must be between 0 and 255. Private int red; private int green; private int blue; private String name; private void check (int red, int green, int blue) {if (red)

< 0 || red >

| 255 | | green |

< 0 || green >

| 255 | | blue |

< 0 || blue >

{throw new IllegalArgumentException ();}} public SynchronizedRGB (int red, int green, int blue, String name) {check (red, green, blue); this.red = red; this.green = green; this.blue = blue This.name = name;} public void set (int red, int green, int blue, String name) {check (red, green, blue); synchronized (this) {this.red = red; this.green = green; this.blue = blue This.name = name;}} public synchronized int getRGB () {return ((red 255 | | blue)

< 0 || blue >

{throw new IllegalArgumentException ();}} public ImmutableRGB (int red, int green, int blue, String name) {check (red, green, blue); this.red = red; this.green = green; this.blue = blue This.name = name;} public int getRGB () {return ((red)

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