Синхронизация важна в многопоточном программировании, поскольку она предотвращает конфликты между потоками, которые могут привести к непредсказуемым результатам. Java предлагает два основных способа синхронизации: ключевое слово synchronized
и класс ReentrantLock
.
Пример использования ключевого слова synchronized
:
public class Counter { private int count = 0; public synchronized void increment() { count++; } public synchronized int getCount() { return count; } }
В этом примере increment()
и getCount()
синхронизированы, что означает, что только один поток может выполнять один из этих методов в одно и то же время.
Теперь взглянем на пример с использованием ReentrantLock
:
import java.util.concurrent.locks.ReentrantLock; public class Counter { private final ReentrantLock lock = new ReentrantLock(); private int count = 0; public void increment() { lock.lock(); try { count++; } finally { lock.unlock(); } } public int getCount() { lock.lock(); try { return count; } finally { lock.unlock(); } } }
Здесь ReentrantLock
используется для того же самого — защиты доступа к переменной count
. Но почему бы не использовать synchronized
вместо ReentrantLock
, ведь он кажется проще?
Есть несколько причин, по которым ReentrantLock
может быть предпочтительнее:
- Больше гибкости:
ReentrantLock
позволяет попытаться захватить блокировку и отказаться от попытки, если блокировка не доступна. Это не возможно сsynchronized
. - Условное ожидание:
ReentrantLock
может использоваться сCondition
для управления потоками, которые пока не могут продолжить работу. - Возможность прерывания блокировки: Если поток ожидает блокировки, то его можно прервать, вызвав
lockInterruptibly()
.
Таким образом, выбор между synchronized
и ReentrantLock
во многом зависит от конкретной ситуации. Если нужна простая синхронизация, synchronized
будет вполне достаточно. Однако, если требуется более сложный контроль над блокировками, ReentrantLock
предоставляет больше возможностей.
Добавить комментарий