Фрагмент synchronized(X.class)
использует экземпляр класса в качестве монитора. Поскольку существует только один экземпляр класса (объект, представляющий метаданные класса во время выполнения), в этом блоке может находиться один поток.
При synchronized(this)
блок охраняется экземпляром. Для каждого экземпляра только один поток может войти в блок.
synchronized(X.class)
используется, чтобы убедиться, что в блоке ровно одна нить. synchronized(this)
гарантирует, что для каждого экземпляра существует ровно один поток. Если это делает фактический код в блоке потокобезопасным, зависит от реализации. Если изменить только состояние экземпляра synchronized(this)
достаточно.