Java concurrency Programming (iii) Adding new atomic operations to thread-safe classes

Source: Internet
Author: User

The Java class library includes a number of useful "base module" classes. In general, we should prefer to reuse these existing classes instead of creating new ones. : Reuse can reduce development effort, develop risk (because existing classes are already tested), and maintenance costs. Sometimes, a thread-safe class can support all the operations we need, but many other times, the existing class can only support most of the operations, and it is necessary to add a new operation without breaking the thread security.

If we need a thread-safe list, he needs to provide an atomic "if not then join (put-if-absent)" operation. The Synchronized List class has implemented most of the functionality, and we can construct an implementation based on the Contains method and the Add method it provides.

There are four ways to implement this atomic operation.


The first approach, and the safest method, ischange the original class。

But this is generally impossible, because you may not be able to access or change the source of the class. To change the original class, you need a deep understanding of the synchronization strategy in the code, so that the ability to add functionality and the original design consistent. Assuming that the new method is added directly to the class, it means that all the code that implements the synchronization strategy is still in one source file, making it easier to understand and maintain.


Another method that canextension (inheritance) This class--If the original class was designed with scalability in mind.

For example, we can design a bettervector to extend the Vector and add a new method putifabsent.

public class Bettervector<e> extends Vector<e>{public synchronized boolean putifabsent (E x) {Boolean absent = !contains (x); if (absent) add (x); return absent;}}

Extension vectors are very easy, but not all classes expose the state to subclasses like vectors, so it is not appropriate to use such a method.

The "extended" method is relatively fragile, mainly because the implementation of the synchronization strategy is separated into multiple source files, assuming that the underlying class changes the synchronization policy, change the different locks to protect the state, then the subclass will be destroyed.


The third method,using auxiliary classes, and implement the client locking mechanism.

For some classes, such as the collections.synchronizedlist encapsulated ArrayList, the first two methods do not work because the customer code does not know the type of the List object that is returned in the synchronous wrapper factory method. In this way, the extension code is placed in a "helper class" in the form of client lock.

So we wrote the Listhelper helper class very naturally.

public class Listhelper<e>{public List<e> List = collections.synchronizedlist (New arraylist<e> ()); Public synchronized Boolean putifabsent (E x) {Boolean absent =!list.contains (x); if (absent) List.add (x); return absent;}}


It's no problem at all, but unfortunately, it's a wrong way.

Although Putifabsent has been declared as synchronized, it is locked on the listhelper and the List is locked with its own or internal objects. Listhelper only brings the illusion of synchronization,

In the documentation for the vector and synchronization wrapper classes, it is stated that they support client locking by means of a vector or internal lock of the encapsulated container. Below we give the correct client lock.

public class Listhelper<e>{public List<e> List = collections.synchronizedlist (New arraylist<e> ()); public boolean putifabsent (E x) {synchronized (list) {Boolean absent =!list.contains (x); if (absent) List.add (x); return Absent;}}}

Extending a class by adding an atomic operation is fragile because it distributes the lock code of the class across multiple classes. However, client locking is more vulnerable because it places the lock code of the class in other classes that are completely unrelated to it.


The fourth method, usingcombination (composition)The way.

Public  class Improvedlist<t> implements list<t> {public final list<t> list;public Improvedlist ( List<t> list) {this.list = list;} Public synchronized Boolean putifabsent (T x) {Boolean absent =!list.contains (x), if (absent) List.add (x); return absent;} //... Other methods of entrusting the list in a similar way}

The improvedlist adds an extra layer of locking through its own built-in lock. It does not care whether the underlying list is thread-safe, and even if the list is not thread-safe or changes its yoke, improved provides a consistent locking mechanism for thread safety. Although the additional synchronization layer may cause a slight performance penalty, improvedlist is more robust than the lock-up strategy for simulating an object. In fact, we use the Java monitor pattern to encapsulate an existing list, and to ensure thread safety by simply having an unexpected non-reference to the underlying list in the class.


Java concurrency Programming (iii) Adding new atomic operations to thread-safe classes

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.