Java Quick Reference
  Language Fundamentals
  Operators and Assignments
  Flow Control and Exceptions
  Declarations and Access Control
  Garbage Collection
  Overloading and Overriding
  Threads
  The java.lang Package
  The java.util Package
  The java.awt Package
  The java.io Package
  References
  Miscellaneous Notes
  Tips & Traps
  Mock Exams

Threads - Thread Synchronization

  • every instance of class Object and its subclass's has a lock
  • primitive data type fields (Scalar fields) can only be locked via their enclosing class
  • fields cannot be marked as synchronized however they can be declared volatile which orders the way they can be used or you can write synchronized accessor methods
  • array objects can be synchronized BUT their elements cannot, nor can their elements be declared volatile
  • Class instances are Objects and can be synchronized via static synchronized methods

Synchronized blocks

  • allow you to execute synchronized code that locks an object without requiring you to invoke a synchronized method
    synchronized( expr ) {
        // 'expr' must evaluate to an Object
    }

Synchronized methods

  • declaring a method as synchronized ie synchronized void f() is equivalent to
    void f() { synchronized(this) {
        // body of method
      } 
    }
  • the synchronized keyword is NOT considered part of a method's signature. IT IS NOT AUTOMATICALLY INHERITED when subclasses override superclass methods
  • methods in Interfaces CANNOT be declared synchronized
  • constructors CANNOT be declared synchronized however they can contain synchronized blocks
  • synchronized methods in subclasses use the same locks as their superclasses
  • synchronization of an Inner Class is independent on it's outer class
  • a non-static inner class method can lock it's containing class by using a synchronized block
    synchronized(OuterClass.this) {
        // body 
    }

Locking

  • locking follows a built-in acquire-release protocol controlled by the synchronized keyword
  • a lock is acquired on entry to a synchronized method or block and released on exit, even if the exit is the result of an exception
  • you cannot forget to release a lock
  • locks operate on a per thread basis, not on a per-invocation basis
  • Java uses re-entrant locks ie a thread cannot lock on itself
class Reentrant {

  public synchronized void a() {
      b();
      System.out.println("here I am, in a()");
  }
  public synchronized void b() {
      System.out.println("here I am, in b()");
  }
}
  • in the above code, the synchronized method a(), when executed, obtains a lock on it's own object. It then calls synchronized method b() which also needs to acquire a lock on it's own object
  • if Java did not allow a thread to reacquire it's own lock method b() would be unable to proceed until method a() completed and released the lock; and method a() would be unable to complete until method b() completed. Result: deadlock
  • as Java does allow reentrant locks, the code compiles and runs without a problem
  • the locking protocol is only followed for synchronized methods, it DOES NOT prevent unsynchronized methods from accessing the object
  • once a thread releases a lock, another thread may acquire it BUT there is no guarantee as to WHICH thread will acquire the lock next

Class fields and methods

  • locking an object does not automatically protect access to static fields
  • protecting static fields requires a synchronized static block or method
  • static synchronized statements obtain a lock on the Class vs an instance of the class
  • a synchronized instance method can obtain a lock on the class
    synchronized(ClassName.class) {
        // body 
    }
  • the static lock on a class is not related to any other class including it's superclasses
  • a lock on a static method has no effect on any instances of that class (JPL pg 185)
  • you cannot effectively protect static fields in a superclass by adding a new static synchronized method in a subclass; an explicit block synchronization is the preferred way
  • nor should you use synchronized(getClass()); this locks the actual Class which might be different from the class in which the static fields are declared

Example Code

Overview Thread Class Runnable Interface Thread States Scheduling Ending a Thread
  Execution Synchronization Locking Protocols synchronized keyword wait() notify(), notifyAll()
  Thread Mechanics