Synchronize access to mutable fields

In a multi-threaded environment, accessing mutable data (data that can change) must always be coordinated between readers and writers. The task of making sure that readers and writers don't interfere with each other in undesirable ways is called synchronization. Synchronization can be done with an explicit lock object, but a more common style is to use the intrinsic locks implied by the synchronized keyword.

For example, in a multi-threaded environment, all get and set methods for mutable fields should usually be synchronized methods. This includes primitive fields.

Most classes do not need to be designed for operation in a multi-threaded environment, and can ignore these considerations.

If an object does need to live in a multi-threaded environment, however, then a significant amount of care must be taken to ensure that it is correctly designed.

If an object is immutable, then it's automatically thread-safe. If it's mutable, then extra steps must be taken to ensure thread-safety: every use of every mutable field must be synchronized in some way (usually with using the synchronized keyword).

Here, mutable field simply means a field which might change in any way, after the initial construction of the object. (Objects are never shared between threads until after the object is fully created.) For example,

Remember that all local variables declared in the body of a method are never shared between threads, and so have no thread-safety considerations.

It's a misconception that all mutable primitives except long and double do not need synchronized access.

Example

Note that even the get of the int field is a synchronized method.

import java.util.Date;

/**
* This class is mutable, but thread-safe : the caller never
* needs to perform external synchronization, except when multiple calls
* need to be treated as a single unit.
*
* This class illustrates the three possible cases for fields :
*<ul>
* <li> a primitive (int)
* <li> an immutable object (String)
* <li> a mutable object (java.util.Date)
*</ul>
* Note that in most new code, you should model dates with java.time, not 
* with java.util.Date; here, java.util.Date is used only because it's 
* convenient for exercising mutable objects.
*/
public final class MutablePlanet {

  public MutablePlanet(int id, String name, Date dateOfDiscovery) {
     this.id = id;
     this.name = name;
     //Make a private copy of the dateOfDiscovery argument.
     //This is the only way to keep the this.dateOfDiscovery
     //field private, and shields this class from any changes
     //to the original dateOfDiscovery object which might be
     //made by the caller.
     this.dateOfDiscovery = new Date(dateOfDiscovery.getTime());
  }

  public synchronized int getId() {
     return id;
  }
  public synchronized void setId(int newId) {
    id = newId;
  }

  public synchronized String getName() {
    return name;
  }
  public synchronized void setName(String newName) {
    name = newName;
  }

  /**
  * Returns a defensive copy of the field.
  * The caller of this method can do anything they want with the
  * returned Date object, without affecting the internals of this
  * class in any way.
  */
  public synchronized Date getDateOfDiscovery() {
    return new Date(dateOfDiscovery.getTime());
  }
  public synchronized void setDateOfDiscovery(Date newDiscoveryDate) {
    //change the state of the mutable Date field
    dateOfDiscovery.setTime(newDiscoveryDate.getTime());
  }

  // PRIVATE

  /**
  * A primitive field.
  */
  private int id;

  /**
  * An immutable object field.
  * Strings never alter state after construction.
  */
  private String name;

  /**
  * A mutable object field.
  * The state of a Date can change after construction.
  */
  private Date dateOfDiscovery;
}
 

See Also :
Immutable objects
Remember the types of intrinsic lock
Document thread safety