Using the synchronized modifier

If you have more than one of your threads running at the same time that
access shared objects, it may cause your object to be in an inconsitent state.

The following example shows what strange behaviour may result from not thinking
carefully about the implications of thread programming.

class Person
{
   private String name;
 
   public Person() {
   }
 
   public void setName(String name) {
         this.name = name;
   }
 
   public void printName() {
      if (name.equals("alicia")) {
         // this should never happen, right?  ow!
         if (name.equals("joris")) {
            System.out.println(name);
         }
      }
   }
}
 
public class Main extends Thread
{
   private Person person = null;
   private String changeName = null;
 
   public Main(Person person, String changeName) {
      this.person = person;
      this.changeName = changeName;
   }
 
   public static void main(String args[]) {
      Person p = new Person();
      
      new Main(p, "alicia").start();
      new Main(p, "joris").start();
   }
 
   public void run() {
      while (true) {
         person.setName(changeName);
         person.printName();
      }
   }
}

It creates one object
Person and two threads that infinitely sets its member variable name to
respectively alicia and to joris. Then it goes ahead and calls
the printName method that contains some illogical code: print out the name
only if it contains the string alicia and it contains the string joris.
That should never happen, right?
Well, consider this. We use two threads that operate on the same person object.
Every thread gets to use the processor for a certain time slice. Suppose the time
slice of the first thread ends right after the statement if (name.equals(“alicia”)),
which validates to true. Then the second thread gets its chance to run and
calls setName(“joris”) on the same object. What happens now if the first thread gets
again control over the CPU? Right! The member name has the value joris
and will output so.

Java provides locks (also called monitors) to solve this problem. Making a
method synchronized will lock the object. This means that no other thread can call
a synchronized method on that object. In our example, you not only have to make
the method printName synchronized, but also setName or the problem
will still arise. If you don’t make setName synchronized, it may still be
called by the second thread, while the first thread is in the synchronized method
printName.

So remember: every method that accesses a critical shared resource should have
the synchronized modifier.

Solution:

class Person
{
   private String name;
 
   public Person() {
   }
 
   public synchronized void setName(String name) {
         this.name = name;
   }
 
   public synchronized void printName() {
      if (name.equals("alicia")) {
         // this should never happen, right?  ow!
         if (name.equals("joris")) {
            System.out.println(name);
         }
      }
   }
}
 
public class Main extends Thread
{
   private Person person = null;
   private String changeName = null;
 
   public Main(Person person, String changeName) {
      this.person = person;
      this.changeName = changeName;
   }
 
   public static void main(String args[]) {
      Person p = new Person();
      
      new Main(p, "alicia").start();
      new Main(p, "joris").start();
   }
 
   public void run() {
      while (true) {
         person.setName(changeName);
         person.printName();
      }
   }
}

Sometimes, you don’t want to synchronize the entire method, only the statements that
may modify shared resources (the “critical section”). You can achieve this kind of
functionality by using:

synchronized(this) {

}
or
synchronized(lock) {

}
where lock is an object whose lock is being used.