Пошёл ты с батей в разные магазины купить хлеб. Если ты купишь, то он не должен этого делать, и наоборот - нужен один хлеп. Перед тем как зайти в магазин вы решили созвониться - оба сказали, что не купили. Закэшировали isBought = false. Батя зашёл, вызвал купитьХлебЕслиНикемНеКуплен - батя купил хлеб, ведь isBought==false, стал true.
Теперь зашёл ты, вызвал купитьХле.. и чтобы не проверять и не тратить время на созвон делаешь оптимизацию взяв старое значение(звонил же батя, сказал, что не купил) с локального для тебя(ты - тред) кеша. Думаешь, батя не купил хлеб, ты берёшь. А на самом деле нужно было позвонить. Ты этого не сделал, хлеб у двух.
В мозгу что-то треснуло при чтении второго абзаца. И я ничего не понял из того, что произошло в конце.
Это был пример без использования volatile?