Давайте ответим на этот пример:
class NonThreadSafe {
private int counter = 0;
public boolean countTo10() {
count = count + 1;
return (count == 10);
}
Метод countTo10
добавляет единицу к счетчику, а затем возвращает true, если счетчик достиг 10. Он должен возвращать true только один раз.
Это будет работать, пока только один поток выполняет код. Если два потока запускают код одновременно, могут возникнуть различные проблемы.
Например, если count начинается с 9, один поток может добавить 1 к счету (делая 10), но затем второй поток может войти в метод и добавить 1 снова (делая 11), прежде чем первый поток сможет выполнить сравнение с 10. Затем оба потока выполняют сравнение и обнаруживают, что счетчик равен 11, и ни один из них не возвращает true.
Так что этот код не является потокобезопасным.
По сути, все проблемы с многопоточностью вызваны некоторыми вариациями такого рода проблем.
Решение состоит в том, чтобы гарантировать, что сложение и сравнение не могут быть разделены (например, путем окружения двух операторов каким-либо кодом синхронизации) или путем разработки решения, которое не требует двух операций. Такой код будет поточно-ориентированным.