Как работает функция синхронизации в java?
Так как я начал программировать на Java, мне это интересно (около года или двух). В C мы должны знать другой метод, чтобы правильно избежать взаимоблокировки между потоком, и, следовательно, выбор между методом синхронизации намного больше.
А как насчет Java? Когда мы синхронизируем, как он избегает помещать поток в тупик? Как это работает внутри страны? Отключен ли тупик, потому что мы синхронизировались на более высоком уровне, чем на C (или С++)? Любая документация о тупике и синхронизации в java?
Ответы
Ответ 1
Под капотом он использует два кода opcodes monitorenter
и monitorexit
на уровне байтового кода, который устанавливает/освобождает блокировки на ссылке на объект на глобальном уровне JVM. Я настоятельно рекомендую вам прочитать Как виртуальная машина Java выполняет синхронизацию потоков.
Ответ 2
Основная проблема (-и), с которой мы встречаемся с многопоточным кодом, - это совместное использование данных, и я согласен с тем, что это процесс параллельного вычисления, и это происходит "по-разному", что во время параллализованной обработки потоки нуждаются в доступе для чтения/записи на общих данных.
Ключевое слово java synchronized позволяет следующее:
Он сообщает JVM о блокировке на мониторе объекта или части синхронизированного кода, который дает ему эксклюзивный доступ к этой части кода или объекта.
Вот пример Singleton:
public class Singleton {
private Singleton INSTANCE;
private Singleton() {
}
public Singleton getInstance() {
if (null == INSTANCE) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
Этот Singleton не является потокобезопасным, если поток пытается получить экземпляр, в то время как другой также пытается сделать то же самое (состояние гонки), может случиться так, что до этого номер потока один заканчивает создание экземпляра второй уже имеет доступ к методу getInstance()
и создал свой собственный экземпляр Singleton, что означает, что в момент времени T мы должны иметь два экземпляра Singleton (называемый в данный момент мультитоном).
Чтобы решить эту проблему, мы должны синхронизировать творческое поведение синглтона, это может быть сделано с помощью ключевого слова synchronized
над оператором if самого INSTANCE
:
public class Singleton {
private Singleton INSTANCE;
private Singleton() {
}
public Singleton getInstance() {
synchronized (Singleton.class) {
if (null == INSTANCE) {
synchronized(Singleton.class) {
Singleton inst = new Singleton();
INSTANCE = inst;
}
}
}
return INSTANCE;
}
}
В результате, когда первый поток запрашивает экземпляр Singleton и во время создания, JVM помещает блокировку на мониторе INSTANCE, лишая доступ к INSTANCE, пока нить не завершит свой запрос.
Существуют и другие способы достижения этой цели, цитированная ранее книга является отличным источником обучения, javadoc также.
Ответ 3
Синхронизация на Java гораздо проще, чем в C. Синтаксически это проще, потому что все, что вам нужно сделать для мьютекса, - объявить метод как синхронизированный или использовать
synchronized(someObject)
{
someCode();
}
В то время как в C/С++ вы должны использовать функции, зависящие от операционной системы, для использования мьютекса, или вам нужно использовать библиотеку Boost.
Но подводные камни о тупике все в основном такие же, как на любом языке.
Ответ 4
Краткие ответы:
-
synchronized
и блоки lock
используют монитор, который блокирует семафор заблокированного объекта в течение всего метода или блока.
-
Сам язык Java не предотвращает взаимоблокировки. Это вам, как программисту, чтобы гарантировать, что объекты заблокированы/разблокированы в правильном порядке, чтобы предотвратить конфликт.
Ответ 5
Вам также нужно позаботиться о тупиках в Java. Самый простой способ получить тупик состоит в том, чтобы один поток выполнял блок, синхронизированный по A, а затем другой блок, синхронизированный с B, в то время как другой поток выполняет блок, синхронизированный на B, а затем блок, синхронизированный с A.
Прочитайте учебник по Java о concurrency. И если вы хотите продолжать учиться, прочитайте Java concurrency на практике.
Ответ 6
Вы пробовали google (Java Deadlock)? Первый результат: http://download.oracle.com/javase/tutorial/essential/concurrency/deadlock.html
Здесь вы можете видеть, что при synchronized
все еще происходят взаимоблокировки, поскольку синхронизация не предназначена для предотвращения того, что в первую очередь.
Ответ 7
Я вижу проблему с Singleton выше. Я думаю, что этот класс никогда не будет создан. Пожалуйста, рассмотрите ниже код.
public class Singleton {
private static Singleton INSTANCE;
private Singleton() { }
public static Singleton getInstance() {
synchronized (Singleton.class) {
if (null == INSTANCE) {
synchronized(Singleton.class) {
Singleton inst = new Singleton();
INSTANCE = inst;
}
}
}
return INSTANCE;
}
}