Synchronizing on Objects

Magic Feather example.

Each object has a magic feather called a monitor. When you use the synchronized keyword on a method, you're gaining the monitor of the current object or locking it. As long as a thread possesses the monitor or lock of an object no other thread can get the lock for that object. (Another thread may be able to lock a different object in the same class, however.)

When you use the synchronized modifier to specify that a method is synchronized, you are locking on the particular object whose method is invoked. (Static methods can also be synchronized. In this case, the lock is placed on the java.lang.Class object associated with the object's class.) Since there's only one lock per object, it's not just the synchronized method that can't be invoked by other threads. It's any other synchronized method or block of code in that object.

You can synchronize at a lower level than a method. For example the following program had problems if another thread changed the value of count or this.count while the assignment was taking place.

public class Counter {

  private int count = 0;

  public void count() {
    int localCopy = this.count;
    int limit = localCopy + 100;
    while (localCopy++ != limit)  System.out.println(localCopy);
    this.count = localCopy; 
  }

}

You can fix this by synchronizing the lines of code that refer to the field:

  public void count() {
     
    int localCopy;
    synchronized (this) {
      localCopy = this.count;
    }
    int limit = localCopy + 100;
    while (localCopy++ != limit) System.out.println(localCopy);
    synchronized (this) {
      this.count = localCopy; 
    }
  }

Note, however, that this "solution" basically prevents the correct current value of count from being read while the count() method is running. We really need a getCount() method to demonstrate this.


Previous | Next | Top | Cafe au Lait

Copyright 1997, 2001, 2002 Elliotte Rusty Harold
elharo@metalab.unc.edu
Last Modified November 1, 2002