Java multithreaded Programming Mode Combat Guide (ii): Immutable object Mode-Reprint

Source: Internet
Author: User
Tags ibm developerworks

This article by oneself first published on the Infoq Chinese site: http://www.infoq.com/cn/articles/java-multithreaded-programming-mode-immutable-object. Reprint Please specify Huang Wenhai Source: http://viscent.iteye.com.

In the case of multi-threaded shared variables, in order to ensure data consistency, it is often necessary to lock the access of these variables. And the lock itself brings some problems and overhead. The immutable object mode allows us to guarantee the thread safety of shared variable access without the use of locks, while avoiding the problems and overhead that can be caused by introducing locks.

Immutable Object Mode Introduction

In a multithreaded environment, an object is often shared by multiple threads. In this case, if there are multiple threads that modify the state of the object concurrently, or if one thread reads the state of the object and another thread attempts to modify the state of the object, we have to do some synchronous access control to ensure data consistency. These synchronous access controls, such as explicit locks and CAS operations, introduce additional overhead and problems, such as context switching, latency, and ABA issues. The intent of the immutable object pattern is to make the shared object "inherently" thread-safe by using an externally visible state immutable object (that is, immutable object) without additional synchronization access control. This ensures data consistency and avoids the additional overhead and problems associated with synchronous access control, and simplifies programming.

The so-called State immutable object, that is, once the object is created, its externally visible state remains unchanged, such as String and Integer in Java. This is easy to understand, but it is not enough to guide us in the practical work of using immutable object mode. Let's look at a typical application scenario, which not only helps us understand it, but also helps to apply it in a real environment.

A vehicle management system to track the location of the vehicle, we can set the vehicle location information as shown in Listing 1 model.

Listing 1. State-Variable location information model (non-thread safe)
public class Location {private double x;private double y;public location (double x, double y) {this.x = X;this.y = y;} Public double GetX () {return x;} Public double GetY () {return y;} public void SetXY (double x, double y) {this.x = X;this.y = y;}}

When the system receives the new vehicle coordinate data, it needs to call the location's SetXY method to update the position information. Obviously, the setxy in Listing 1 is non-thread-safe because the write operation to coordinate data x and Y is not an atomic operation. When SetXY is called, if the X write is complete and Y has other threads reading the location information before it begins to write, the thread may read a location that the tracked vehicle never had. To make the SetXY method thread-safe, we need access control with locks. Although the location information of tracked vehicles is always changing, we can also model the location information as immutable objects, as shown in Listing 2.

Listing 2. Position information model with immutable state
Public final class Location {public final double x;public final double y;public location (double x, double y) {this.x = X;t His.y = y;}}

When using a state-immutable location information model, updating a vehicle's location information is accomplished by replacing the entire object that represents the location information (that is, the site instance) when the vehicle's position changes. This is shown in Listing 3.

Listing 3. Update vehicle location information with immutable objects
public class VehicleTracker {private map<string, location> locmap = new concurrenthashmap<string, location= "" St Yle= "margin:0px; border:0px; padding:0px; " > ();p ublic void UpdateLocation (String vehicleid, location newlocation) {locmap.put (Vehicleid, NewLocation);}}

Thus, the so-called State immutable object does not mean that the state of the real-world entity being modeled is immutable, but rather a decision that we make when modeling: the state of the real-world entity is always changing, but we can model these entities with immutable objects of state.

Immutable schema for Object mode

The main players in immutable object mode are the following. Its class is shown in Figure 1.

Figure 1. Immutable class diagram for object mode

    • Immutableclass: A class that is responsible for storing a set of immutable states. This class does not expose any method that can modify its state, its main methods and responsibilities are as follows:

      Getstatex , Getstaten: These getter methods return the values of state-dependent variables maintained by the class. These variables derive values from the parameters of their constructors when the object is instantiated.

      getstatesnapshot: Returns a snapshot of the set of States maintained by this class.

    • Manipulator: Responsible for maintaining changes in the state of the real world entities modeled by Immutableclass. When the corresponding real-world entity state changes, the class is responsible for generating a new instance of Immutableclass to reflect the new state.

      Changestateto: Generates an instance of the new Immutableclass based on the new status value.

The use of immutable objects mainly includes the following types:

gets the value of a single state : The dependent getter method that invokes the immutable object is implemented.

get a snapshot of a set of States : Immutable objects can provide a getter method that requires a defensive copy of its return value or returns a read-only object to prevent its state from being compromised and changed.

generate a new Immutable object instance : When the state of the modeled object changes, a new immutable object instance is created to reflect this change.

Typical interaction Scenario 2 for immutable object mode is as follows:

Figure 2. Immutable sequence diagram for object mode

1~4, the client code gets the individual state values of the Immutableclass.

5. The client code calls manipulator's Changestateto method to update the application's state.

6. Manipulator creates a new Immutableclass instance to reflect the new state of the app.

7~9, the client code gets a snapshot of the state of the new Immutableclass instance.

A strictly immutable object to meet all of the following conditions:

1) The class itself uses the final decoration : To prevent its subclasses from changing the behavior of its definition;

2) All fields are final decorated : Using the final decoration is not only semantically stating that the reference to the decorated field is immutable. More importantly, this semantics is guaranteed by the JMM (Java Memory Model) in the multithreaded context that the initialized security of the referenced object of the modified field, that is, when the final decorated field is visible to other threads, it must be initialized. Conversely, a non-final-modified field may cause some unpredictable results because of a lack of this assurance that a thread might "see" a field when it has not been initialized.

3) during the creation of an object, The This keyword is not disclosed to other classes : Prevents other classes (such as anonymous inner classes of the class) from modifying their state during the object creation process.

4) Any field that refers to other mutable objects (such as collections, arrays, and so on) must be private, and these field values cannot be exposed externally. If you have a method to return these field values, you should make a defensive copy (defensive copy).

Immutable Object Mode Combat case

When processing MMS messages sent by a value-added service provider (vasp,value-added service Provider) to mobile phone end users, a MMS gateway system needs to select the corresponding MMS Center (MMSC) based on the prefix of the receiver number of the MMS (for example, 1381234). Multimedia Messaging Service Center), then forwards the message to the selected MMS Center, which is responsible for docking the telco network to send MMS messages to the mobile end user. The MMS Center is a separate part of the MMS Gateway system, which interacts with the network. This process of choosing the MMS Center is called routing (Routing). This correspondence between the phone number prefix and the MMS center is called the routing table. The routing table may change during the software operation. For example, the new MMS Center for business expansion, the addition of a prefix for a number, and so on. Although the routing table is the data that is shared by multithreading in this system, the frequency of these data changes is not high. Therefore, even in order to ensure thread safety, we do not want to access the data to lock and other concurrent access control, so as not to incur unnecessary overhead and problems. At this point, the immutable object pattern comes in handy.

The maintenance path can be modeled as an immutable object by a table, as shown in Listing 4.

Listing 4. Maintaining the routing table with immutable objects

Public final class Mmscrouter {//with volatile modifiers to ensure the visibility of the variable in a multithreaded environment private static volatile Mmscrouter instance = new Mmscrouter (         ); Maintain the mapping relationship between the phone number prefix and the MMS Center private final map<string, mmscinfo> routemap;public mmscrouter () {//To load data from a database table into memory, Save As Mapthis.routemap = Mmscrouter.retrieveroutemapfromdb ();} private static map<string, mmscinfo> Retrieveroutemapfromdb () {map<string, mmscinfo> Map = new hashmap< String, mmscinfo> ();//Omit other code return map;} public static Mmscrouter getinstance () {return instance;} /** * Based on the phone number prefix to obtain the corresponding MMS center information * * @param msisdnprefix * Mobile phone number prefix * @return MMS Center Information */public Mmscinfo Getmmsc (String msi Sdnprefix) {return routemap.get (msisdnprefix);} /** * Update the instance of the current mmscrouter to the specified new instance * * @param newinstance * New Mmscrouter instance */public static void Setinstance (Mmscrou ter newinstance) {instance = newinstance;} private static map<string, mmscinfo> deepcopy (map<string, mmscinfo> m) {map<string, mmscinfo> result = New Hashmap<string, MMscinfo> (); for (String Key:m.keyset ()) {Result.put (Key, New Mmscinfo (M.get (key));} return result;} Public map<string, Mmscinfo> Getroutemap () {//Make defensive copy return Collections.unmodifiablemap (Deepcopy (Routemap));}}

The relevant data for the MMS center, such as the MMS Center device number, the URL, and the maximum supported attachment size, are also modeled as an immutable object. This is shown in Listing 5.

Listing 5. Use immutable objects to represent MMS Center information

Public final class Mmscinfo {/** * device number */private final string deviceid;/** * MMS Center URL */private Final String url;/** * this MMS Maximum attachment size allowed for center */private final int maxattachmentsizeinbytes;public mmscinfo (string deviceID, string url, int maxattachmentsizeinbytes) {This.deviceid = Deviceid;this.url = Url;this.maxattachmentsizeinbytes = Maxattachmentsizeinbytes;} Public Mmscinfo (Mmscinfo prototype) {This.deviceid = Prototype.deviceid;this.url = Prototype.url; This.maxattachmentsizeinbytes = prototype.maxattachmentsizeinbytes;} Public String Getdeviceid () {return deviceID;} Public String GetUrl () {return URL;} public int getmaxattachmentsizeinbytes () {return maxattachmentsizeinbytes;}}

MMS Center Information Change frequency is also not high. Therefore, when the MMS gateway system is notified through the network (socket connection) that the MMS center information itself or the routing table changes, the gateway system regenerates new Mmscinfo and mmscrouter to reflect this change. This is shown in Listing 6.

Listing 6. Handling changes to the MMS Center, routing table

/** * Classes docked with operations center (Operation and Maintenance centre) * */public class Omcagent extends thread{@Override public  void Run () {Boolean istablemodificationmsg=false; String Updatedtablename=null;  while (true) {  ///Omit other code/*   * Read the message from the socket connected to the OMC and parse it,   * After parsing to the data table update message, reset the Mmscrouter instance.   */  if (istablemodificationmsg) {  if ("Mmscinfo". Equals (Updatedtablename)) {  Mmscrouter.setinstance (New Mmscrouter ());  }  }  Omit other code  }}}  

The code above calls Mmscrouter's Setinstance method to replace the instance of Mmscrouter with the newly created instance. The newly created Mmscrouter instance generates multiple instances of the new mmscinfo through its constructor.

In this case, Mmscinfo is a strictly immutable object. Although Mmscrouter provides an external setinstance method for changing the value of its static field instance, it is still visible as an equivalent immutable object. This is because the Setinstance method only changes the object that the instance variable points to, and the instance variable uses the volatile modifier to ensure its memory visibility between multiple threads. This means that Setinstance's change to the instance variable does not require a lock and can be thread-safe. Other code does not need to lock the routing information when calling Mmscrouter's related methods.

From the class diagram in Figure 1, the Omcagent class (see Listing 6) is a manipulator participant instance, and Mmscinfo, Mmscrouter is a Immutableclass participant instance. By using immutable objects, we can address both the not-so-frequent changes in the routing table, the MMS center, and the code that uses the routing table in the system to avoid the overhead and problems of concurrent access control.

Evaluation and implementation of immutable object model

Immutable objects are inherently thread-safe, and multiple threads share an immutable object without the use of additional concurrency access control, which allows us to avoid the overhead and problems of concurrency access control such as explicit lock (Explicit lock), simplifying multithreaded programming.

Immutable object mode is especially useful for the following scenarios.

the state of the modeled object changes infrequently: As demonstrated in this case scenario, a dedicated thread (the thread where the manipulator participant resides) can be set up to create a new immutable object when the state of the modeled object changes. Other threads just read the state of the immutable object. A small trick in this scenario is that manipulator's reference to immutable objects uses the volatile keyword modifier to avoid explicit locks (such as synchronized) and to guarantee memory visibility between multiple threads.

while writing a set of related data, it is necessary to ensure atomicity : This scenario is typically used to ensure the atomicity of the operation by using an explicit lock. However, if the immutable object mode is used to "combine" This set of related data into an immutable one, then the operation of this set of data can be guaranteed atomically without explicit locking, which simplifies programming and improves the efficiency of code operation. The example of vehicle location tracking at the beginning of this article is this scenario.

use an object as a secure HashMap key: We know that an object as a HashMap key is "put" in the HashMap, if the object state changes cause its hash code changes, Can cause the associated value to be fetched when the same object is used as the key, although there is indeed an entry with that object as key in the HashMap. Conversely, because the immutable object's state is constant, its hash code does not change. This makes the immutable object very suitable for use as a HashMap key.

There are several issues to be aware of when implementing the immutable object pattern:

the state of the modeled object is changed more frequently : it is not possible to use immutable object mode at this time. Just because this means creating new immutable objects frequently and therefore increasing the burden and CPU consumption of the GC (garbage Collection), we need to consider the scale of the objects being modeled, the JVM memory allocations of the code target runtime, and the system's requirements for throughput and responsiveness. If these factors are comprehensive enough to meet the requirements, then modeling with immutable objects is also possible.

use an equivalent or approximate immutable object : Sometimes it is difficult to create immutable objects in strict sense, but it is also advantageous to make the immutable objects as close as possible to the immutable objects in strict sense.

Defensive copy : If the immutable object itself contains some states that need to be exposed, and the corresponding fields themselves are mutable (such as HashMap), then the method to return these fields requires a defensive copy to prevent external code from modifying its internal state. As shown in the Getroutemap method in the code in Listing 4.

Summarize

This article describes the intent and architecture of the immutable object mode. and combined with the author's work experience provides a practical case to demonstrate the use of the model of the typical scenario, on this basis, the model is evaluated and shared in the actual use of the model needs to be noted.

Reference Resources
    • Source code for this article read online: https://github.com/Viscent/JavaConcurrencyPattern/
    • Brian Göetz,java theory and practice:to mutate or not to mutate?:http://www.ibm.com/developerworks/java/library/ J-jtp02183/index.html
    • Brian Göetz et al.,java Concurrency in practice
    • Mark Grand,patterns in Java,volume 1, 2nd Edition
    • Java Language specification,17.5. Final Field semantics:http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html
About the author

Huang Wenhai , has many years of Agile project management experience and a wealth of technical guidance experience. Focus on Agile Development, Java multithreaded programming, and web development. Published numerous articles on the Infoq Chinese station and IBM Developerworks. Its blog: http://viscent.iteye.com/

Java multithreaded Programming Mode Combat Guide (ii): Immutable object Mode-Reprint

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.