В Java можно создавать потоки, каждый поток выполняет код, и если несколько потоков запущены одновременно, то и код исполняется одновременно. Это позволяет сделать программы более быстрыми, потому что код может выполняться на разных процессорах (ядрах процессора). Программы могут быть более отзывчивыми, т.е. один поток производит вычисления, другой их отображает. Т.е. не нужно ждать, пока действие закончится, чтобы увидеть какой-то результат.

Процесс — это понятие из Операционной системы, каждая запущенная программа — это отдельный процесс. Потоки — более высокоуровневое понятие, Java сама создаёт и управляет своими потоками. В будущем в Java появятся легковесные (зеленые) потоки, пока что потоки — это ценный ресурс, слишком много их создавать не нужно.

Программировать с несколькими потоками трудно, потому что могут мешать друг другу, каждый раз они исполняются с разными задержками относительно друг друга, поэтому при каждом запуске ошибки могут проявляться или не проявляться.

Примитивы синхронизации

Это базовые возможности Java по работе с потоками, встроены в язык.

Понятие — монитор. Это объект, который потоки могут забирать себе и отдавать. Кусочек кода помечается с помощью монитора:

synchronized (monitor) {
    код
}

Когда выполнение доходит до блока, поток забирает монитор себе. Любой другой поток, попадая в этот блок, тоже пытается забрать себе монитор, но монитор уже взят, поэтому поток зависает перед началом блока. Когда первый поток закончил выполнять код, монитор отдаётся. Один из тех потоков, кто ждал на мониторе, получает его и тоже начинает выполнять код.

В результате код, обрамленный в synchronized одновременно может выполнять только один поток.