Why is `synchronized (new Object()) {}` a no-op?

The FAQ is not the authority on the matter; the JLS is. Section 17.4.4 specifies synchronizes-with relationships, which feed into happens-before relationships (17.4.5). The relevant bullet point is:

  • An unlock action on monitor m synchronizes-with all subsequent lock actions on m (where “subsequent” is defined according to the synchronization order).

Since m here is the reference to the new Object(), and it’s never stored or published to any other thread, we can be sure that no other thread will acquire a lock on m after the lock in this block is released. Furthermore, since m is a new object, we can be sure that there is no action that previously unlocked on it. Therefore, we can be sure that no action formally synchronizes-with this action.

Technically, you don’t even need to do a full cache flush to be up to the JLS spec; it’s more than the JLS requires. A typical implementation does that, because it’s the easiest thing the hardware lets you do, but it’s going “above and beyond” so to speak. In cases where escape analysis tells an optimizing compiler that we need even less, the compiler can perform less. In your example, escape analysis can could tell the compiler that the action has no effect (due to the reasoning above) and can be optimized out entirely.

Leave a Comment