Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: edits

...

Code Block
bgColor#FFCCCC
// Client
public class BookWrapper {
  private final Book book;

  BookWrapper(Book book) {
    this.book = book;
  }

  public void issue(int days) {
    book.issue();
  }

  public Calendar getDueDate() {
    return book.getDueDate();
  }

  public void renew() {
    synchronized(book) {
      if (book.getDueDate().after(Calendar.getInstance())) {
        throw new IllegalStateException("Book overdue");
      } else {
        book.issue(14); // Issue book for 14 days
      }
    }
  }
}

If class Book changes its synchronization policy in the future, the BookWrapper class's locking strategy might silently break. For instance, the Bookwrapper class's locking strategy will definitely break if Book is modified to use an internal private lock, as recommended by CON04-J. Synchronize using an internal private final lock object. This is because threads that call getDueDate() of class BookWrapper may perform operations on the thread-safe Book using its new locking policy, however, threads that call method renew() will always synchronize on the intrinsic lock of the Book instance. Consequently, the implementation will use two different locks.

...

Code Block
bgColor#ccccff
public class BookWrapper {
  private final Book book;
  private final Object lock = new Object();

  BookWrapper(Book book) {
    this.book = book;
  }

  public void issue(int days) {
    synchronized(lock) {
      book.issue();
    }
  }

  public Calendar getDueDate() {
    synchronized(lock) {
      return book.getDueDate();
    }
  }

  public void renew() {
    synchronized(lock) {
      if (book.getDueDate().after( Calendar.getInstance())) {
        throw new IllegalStateException("Book overdue");
      } else {
        book.issue(14); // Issue book for 14 days
      }
    }
  }
}

Wiki Markup
Consequently, itsthe {{BookWrapper}} class's locking strategy is independent of the locking policy of the {{Book}} instance. This solution incurs a very small performance penalty but the resulting code is much more robust \[[Goetz 06|AA. Java References#Goetz 06]\].

...