В вашем случае out of sync
никогда не будет напечатан, потому что для вашей ситуации многопоточность реализована правильно: критические методы, которые выполняют последовательность операций и, следовательно, не являются atomi c, ведут себя как atomi c методы с использованием ключевого слова synchronized
в методе.
Предположим, что объявлен блок кода synchronized (x)
. Первый поток, который входит в этот блок кода, получает блокировку объекта x
и успешно выполняет этот блок кода.
Любой не первый поток, который пытается войти в блок на том же объекте x
, "приостановлен" "путем помещения потока в пул блокировок из x
. Как только поток, который в настоящее время имеет блокировку, покидает блок synchronized (x)
, случайный поток из пула блокировок становится следующим потоком, выполняющим этот блок.
При использовании synchronized
в методе экземпляра он фактически то же самое, что обертывание всего содержимого метода с помощью synchronized (this)
. (Для методов static
это будет объект класса включающего класса.)
Итак, в вашем случае есть один экземпляр класса A
, и вся синхронизация происходит с ним.
Если вы хотите увидеть сообщение out of sync
, попробуйте удалить ключевое слово synchronized
. Затем через некоторое время вы должны увидеть ожидаемое сообщение out of sync
.
Примечания:
- Поскольку
out of sync
является сообщением, его, вероятно, следует напечатать на System.err
, а не System.out
. - Вместо
a.rand.nextInt(2) == 1
вы можете использовать a.rand.nextBoolean()
. - Имея
class B
поле доступа rand
из class A
, инкапсуляция нарушается, вы можете захотеть дать class A
метод randomBoolean()
, который выполняет return rand.nextBoolean()
, и вызывает этот метод randomBoolean()
из class B
. - Наличие одинаковых имен переменных с разными значениями в разных контекстах может сбивать с толку. В
class A
переменные a
и b
обозначают два числа, в других контекстах переменные a
и b
относятся к экземплярам class A
и class B
. Попробуйте переименовать поля class A
во что-нибудь другое, например number1
и number2
.