Метод tryLock
является поточно-ориентированным. Он делает то, что должен делать (в соответствии с javadoc) надежно.
Однако использование вами trylock
приводит к не поточно-ориентированной реализации increment
и * 1006. *. Если вы собираетесь использовать trylock
в этой ситуации, вам нужно будет сделать что-то вроде этого:
try {
while (!lock.tryLock()) { } // Try to get the lock until you get it
counter++;
} finally {
lock.unlock();
}
Но это плохая идея, потому что вы эффективно заняты, ожидая блокировки. Лучшее решение с использованием Lock
было бы:
try {
lock.lock(); // Block until the lock is acquired.
counter++;
} finally {
lock.unlock();
}
Но если вы ищете решение без блокировки, то вам следует использовать атомарный тип:
java.util.concurrent.atomic.LongAdder
( javadoc ) для Java 8 и более поздних версий, java.util.concurrent.atomic.AtomicLong
( javadoc ) всех версий Java, начиная с Java 5 включительно.
Очевидно, LongAdder
работает лучше, если есть много споров:
Обратите внимание, что потокобезопасность на самом деле сложно определить точно. Вам нужно начать с поведенческой спецификации правильного поведения алгоритма. Тогда вы можете сказать, что реализация алгоритма.
Определение: если алгоритм корректен в соответствии со спецификацией при работе в системе с одним процессором, то он поточно-безопасный если оно также всегда правильно в соответствии со спецификацией при наличии нескольких процессоров.
Из этого мы видим, что:
- thread-безопасность является спорной, если алгоритм не соответствует его поведенческой спецификации в одном случае процессора, и