Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

5 Tips to Make Your Classes Thread Safe

DZone's Guide to

5 Tips to Make Your Classes Thread Safe

Remember folks, safety first! Here are five ways to ensure your classes are safe.

· Java Zone
Free Resource

What every Java engineer should know about microservices: Reactive Microservices Architecture.  Brought to you in partnership with Lightbend.

While testing vmlens, a tool to find data races in java applications, on open source projects, I found the following 5 tricks how to make classes thread safe.

1) Declare Immutable Member Variables as Final

Always declare immutable member variables as final. This makes sure that your class behaves correctly independent on how it is used. Take for example the field fieldAccessor in the class java.lang.reflect.Field.

   private FieldAccessor fieldAccessor; 

   private FieldAccessor getFieldAccessor(Object obj)
        throws IllegalAccessException
    {
        boolean ov = override;
        FieldAccessor a = (ov) ? overrideFieldAccessor : fieldAccessor;
        return (a != null) ? a : acquireFieldAccessor(ov);
    }

Since it is not synchronized and not declared volatile, a thread reading this field might not see a completely initialized object as described in DoubleCheckedLocking But since the created object type sun.reflect.UnsafeQualifiedIntegerFieldAccessorImpl only uses final problem, there is no problem. Threads reading this field will always see a fully initialized object or null.

2) Create Objects Eagerly

Using final fields forces you to initialize your objects in the constructor. Lazy initialization of your objects on the other side is almost never a good idea in concurrent programs.

Take for example the old version from org.apache.commons.lang.StringEscapeUtils. It uses the lazy initialized class org.apache.commons.lang.Entities$LookupEntityMap:

       private String[] lookupTable() {
            if (lookupTable == null) {
                createLookupTable();
            }
            return lookupTable;
        }

This only works with locks or synchronization. Much better is the new version org.apache.commons.lang3.StringEscapeUtils witch eagerly creates the lookup tables and also uses a final field.

 public static final CharSequenceTranslator ESCAPE_XML10 =
        new AggregateTranslator(
            ... 

3) Use Volatile for Mutable Boolean Variables

Mutable boolean fields are often used for controlling the flow of your application. For example to control the life cycle of a thread the following pattern can be used:

private volatile boolean isWorking;

while(isWorking)
{
  // do something
}

Use a volatile field to make the changes done in one thread visible in other threads.

4) Check 3rd Party Classes

A typical example for not doing so, is the use of the non thread safe java.util.date as member variable without synchronization. Therefore always check if the class is documented as thread safe. If not chances are high that it is not.

5) Test

Like all other features of your application, concurrency must be tested. In my next Blog post I will write how to test concurrency. In the meanwhile you can give vmlens a trial, which helps you to detect data races during testing.

Microservices for Java, explained. Revitalize your legacy systems (and your career) with Reactive Microservices Architecture, a free O'Reilly book. Brought to you in partnership with Lightbend.

Topics:
java ,multithreading ,concurrency

Published at DZone with permission of Thomas Krieger, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}