Нужна синхронизация для инкрементного счетчика?

Я использую целое число в качестве счетчика. Целое число будет только увеличиваться, и наверняка несколько потоков будут увеличивать его одновременно. Значение этого счетчика считывается в конце выполнения программы, когда никакой другой поток не будет пытаться получить доступ к его значению.

Я предполагаю, что мне не нужно использовать блокировку или какую-либо синхронизацию для такого счетчика только приращения. Это правильно? Я кодирую на Java, если это имеет значение.


person qinsoon    schedule 04.10.2011    source источник


Ответы (1)


Если вы только что использовали переменную int или long, вам понадобится синхронизация — приращение включает в себя чтение/увеличение локально/запись, что далеко не атомарная операция. (Даже если переменная равна volatile, чтобы избежать проблем с устаревшей моделью памяти, у вас все равно будет три отдельных операции с возможностью вытеснения между любой парой из них.)

К счастью, Java предоставляет AtomicInteger и AtomicLong, который можно использовать без какой-либо синхронизации:

private final AtomicLong counter = new AtomicLong();

...

counter.incrementAndGet(); // No need for synchronization
person Jon Skeet    schedule 04.10.2011
comment
Как обычно, отличный ответ Джона Скита. Джон, вы также написали какую-нибудь книгу по программированию на Java, если да, пожалуйста, дайте мне знать :) Мы также будем признательны за рекомендации других книг. - person JavaSa; 01.03.2014
comment
@JavaSa: Нет, я ничего не писал на Java. Тем не менее, я бы настоятельно рекомендовал «Эффективную Java» Джоша Блоха. - person Jon Skeet; 01.03.2014
comment
Спасибо, а у вас есть бесплатные книги, посвященные новым функциям, появившимся в Java с 2005 года? Скажем, для Java 7 и, возможно, Java 8. - person JavaSa; 01.03.2014
comment
@JavaSa: Нет, боюсь, я уже давно не читал книг по Java... - person Jon Skeet; 01.03.2014
comment
См. также docs.oracle.com/javase/tutorial/essential/concurrency/ - person flow2k; 06.06.2017