Java concurrency Programming (iii) Adding a new atomic operation to an existing thread-safe class

Source: Internet
Author: User

The Java class library contains 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 more often, the existing class can only support most operations, and a new operation needs to be added without breaking the thread's security.

Assuming we need a thread-safe list, he needs to provide an atomic "add (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, isModify the original class。

However, this is usually not possible because you may not be able to access or modify the source code of the class. To modify the original class, you need a deep understanding of the synchronization strategy in the code so that the added functionality will be consistent with the original design. If you add the new method directly to the class, it means that all the code that implements the synchronization policy is still in a source code file, making it easier to understand and maintain.

The second method, you 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;}}

Extending the vector is simple, but not all classes expose the state to subclasses like vectors, so it is not appropriate to use this approach.

The "extended" method is weak, mainly because the implementation of the synchronization policy is separated into multiple source code files, and if the underlying class changes the synchronization policy and the different locks are changed to protect the state, the subclass is destroyed.

The third method,using auxiliary classesTo implement the client lock 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. The extension code is then placed in a "helper class" in the form of a client lock.

So we naturally write the Listhelper helper class.

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;}}


I see no problem, but unfortunately, this way is wrong.

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 just brings out the illusion of synchronization,

In the documentation for the vector and synchronization wrapper classes, it is indicated that they are supported by a vector or encapsulated container internal lock to support the client lock. 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, the client lock 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 ways to delegate 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 modifies its yoke, improved provides a consistent locking mechanism for thread safety. Although the additional synchronization layer can cause slight performance loss, improvedlist is more robust than simulating another object's lock-up strategy. In fact, we used the Java monitor pattern to encapsulate the existing list, and to ensure thread safety as long as there was an unexpected non-reference to the underlying list in the class.


Java concurrency Programming (iii) Adding a new atomic operation to an existing thread-safe class

Related Article

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.