Решить проблему атомарности? Просто держите эту модель в уме

Java
Решить проблему атомарности? Просто держите эту модель в уме

предыдущий постНаглядность и упорядоченность, Бывает-прежде чем это сделать, решает две из трех основных проблем параллелизма, сегодня мы поговорим о том, как решить проблему атомарности

Источником проблемы атомарности являетсяпереключение потоков, но в контексте многоядерных процессоров невозможно не допустить переключения потоков.Поскольку так называемая «магия в один фут высотой, Тао в один фут высотой», приходят новые правила:

Взаимное исключение: одновременно выполняется только один поток.

На самом деле смысл приведенного выше предложения таков: изменение общих переменных является взаимоисключающим, то есть другие потоки не могут изменять общие переменные, когда поток A изменяет общие переменные, поэтому нет проблем, что операция прерывается. , так как добиться Что насчет взаимного исключения?

Замок

Друзья, у которых есть понимание параллелизма, могут сразу подумать об этом.ЗамокЭта концепция и ваша первая реакция, скорее всего, будет использовать синхронизированный, вот три распространенных варианта использования синхронизированного:

public class ThreeSync {

	private static final Object object = new Object();

	public synchronized void normalSyncMethod(){
		//临界区
	}

	public static synchronized void staticSyncMethod(){
		//临界区
	}

	public void syncBlockMethod(){
		synchronized (object){
			//临界区
		}
	}
}

Есть некоторые различия в содержании трех синхронизированных замков:

  • Для обычных синхронизированных методов блокировкой является текущий объект экземпляра, обычно это
  • Для статических методов синхронизации блокировкой является объект Class текущего класса, например ThreeSync.class.
  • Для синхронизированных блоков методов блокировка — это объект в синхронизируемых скобках.

Я намеренно добавил комментарий со словами «критическая секция» к трем синхронизируемым кодам, так что же такое критическая секция?

Критическая секция: мы рассматриваем код, требующий взаимоисключающего выполнения, как критическую секцию.

Сказав это, знание, которым делятся со всеми, является поверхностным познанием.Как защитить эффективные критические секции блокировками — ключ, что напрямую связано с тем, будете ли вы писать параллельные ошибки.После понимания содержания этой главы вы обнаружите, что использование неявных блокировок/встроенных блокировок (синхронизированных) или явных блокировок (Lock) ищет эту связь, Отношения правильные, все правильно, посмотрим

Вышеупомянутые три способа блокировки могут быть выражены следующей схемой:

Перед входом в критическую секцию поток пытается заблокировать блокировку(), и если блокировка прошла успешно, он входит в критическую секцию (модифицирует разделяемую переменную), после чего поток, удерживающий блокировку, выполняет код критической секции, он выполняет функцию unlock(), чтобы снять блокировку. В ответ на эту модель люди часто описывают ее как занятие туалетной ямы:

Вот как я помню и понимаю блокировки в первые дни изучения Java, но когда дело доходит до кода, мы легко можем упустить из виду два момента:

  1. Что запираем?
  2. Что мы защищаем?

Объединив эти два предложения, можно ли защитить блокировку ресурсов критической секции? Поэтому нам необходимо дополнительно уточнить приведенную выше модель.

в действительности,Мы все знаем наши замки, чтобы запереть то, что нам нужно защитить., это предложение переведено на ваш язык действий, и вы уже ясно его знаете:

  1. что ты запер
  2. какие ресурсы вы защищаете

Процессор не так умен, как наш мозг, мы должны четко указать, что мы блокируем и какие ресурсы мы хотим защитить, и он будет использовать блокировки для защиты ресурсов, которые мы хотим защитить (общие переменные).

Взяв в качестве примера приведенное выше изображение, ресурс R (общая переменная) — это ресурс, который мы хотим защитить, поэтому нам нужно создать блокировку для ресурса R, чтобы защитить ресурс R. Внимательные друзья могут найти несколько проблем на приведенном выше рисунке:

Существует четкая указывающая связь между LR и R. Когда мы пишем программы, модель в нашем уме часто оказывается правильной, но мы игнорируем это указывающее отношение, так что наша блокировка не может играть роль защиты ресурса R (использовать чужие блокировки для защиты своих вещей или использовать собственные блокировки для защиты своих вещей). защищать свои собственные вещи, защищать чужие вещи), и в конечном итоге привести к одновременным ошибкам,Поэтому, когда вы делаете набросок, найдите эту взаимосвязь в явном виде.

Пунктирная линия слева LR указывает на необязательные переменные Это легко сделать, когда мы пишем программы.Мы не уверены, какой ресурс защищать, и просто смешиваем его.Мы используем LR для защиты защищаемого ресурса R и неразделяемых переменных, которые не нужно защищать. Защищено.На двух примерах можно понять минус

  1. При написании последовательной программы не рекомендуется пытаться...отловить весь метод, так что если есть проблема, то ее трудно локализовать.Причина та же, нам достаточно заблокировать нужные нам ресурсы надежно защищать замками, и никакие другие значимые ресурсы не заблокированы
  2. Чем больше вещей защищает блокировка, тем больше критическая область и тем больше времени требуется потоку от входа в критическую область до выхода из критической области, что заставляет другие потоки ждать дольше, а эффективность параллелизма снижается.Это проблема, связанная с блокировка детализации, которая будет объяснена позже.

Как программисту, лучше просто взять код, чтобы объяснить, что я чувствую себя более непринужденно, и вижу:

public class ValidLock {
	
	private static final Object object = new Object();
	
	private int count;
	
	public synchronized void badSync(){
		//其他与共享变量count无关的业务逻辑
		count++;
	}
	
	public void goodSync(){
		//其他与共享变量count无关的业务逻辑
		synchronized (object){
			count++;
		}
	}
}

Это не означает, что синхронизация не подходит для методов, она просто напоминает всем о необходимости использовать соответствующую степень детализации блокировки для повышения эффективности.

В примере программы счетчика мы часто будем писать:

public class SafeCounter {

	private int count;

	public synchronized void counter(){
		count++;
	}

	public synchronized int getCount(){
		return count;
	}
}

На следующем рисунке показана модель вышеуказанной программы:

Здесь мы блокируем это, что может защитить this.count. Однако некоторые учащиеся считают, что методу getCount не нужно добавлять ключевое слово synchronized, поскольку это операция чтения, которая не будет изменять общие переменные. правило в нашей предыдущей статье.Правила блокировки устройства:

Отпирание замка происходит до последующего запирания замка Другими словами, запись в count, скорее всего, будет невидима для чтения в count, что приводит к грязным чтениям.

Выше мы видели, что одна эта блокировка может защитить несколько ресурсов.Можно ли использовать несколько разных блокировок для защиты ресурса? Взгляните на программу:

public class UnsafeCounter {

	private static int count;

	public synchronized void counter(){
		count++;
	}

	public static synchronized int calc(){
		return count++;
	}
}

Откройте глаза и присмотритесь, один замок — это, другой — UnsafeCounter.class, они оба хотят защитить количество общих переменных, что вы думаете? На следующем рисунке показано отображение модели программы поверхности линии:

Атомарность, заблокируй еще один ресурс.png

Две критические секции защищены двумя разными блокировками, поэтому критические секции не имеют отношений взаимного исключения, поэтому count не может быть защищен, поэтому эта блокировка не имеет смысла.

Суммировать

  1. Чтобы решить проблему атомарности, она должна быть взаимоисключающей, то есть гарантировать, что промежуточное состояние невидимо для внешнего мира.
  2. Блокировки - ключ к решению проблемы атомарности.Знайте точно, что мы блокируем, какие ресурсы должны быть защищены и, что более важно, могут ли ваши блокировки защитить этот защищенный ресурс (на что указывает стрелка на рисунке)
  3. Эффективной критической областью является один вход и один выход, а множественные критические области защищают ресурс, то есть ресурс имеет множественные параллельные входы и множественные выходы, что не играет защитной роли взаимного исключения, а критическая область бесполезна.
  4. Запирание собственной двери может защитить ресурсы, и вам не нужно запирать все сообщество, если вы заблокируете все сообщество, это серьезно повлияет на деятельность других владельцев (проблема детализации блокировки)

В этой статье синхронизированные блокировки используются в качестве примера, чтобы проиллюстрировать, как решить проблему атомарности, в основном, чтобы помочь вам установить макроконцепцию для решения проблемы атомарности, так что независимо от того, какую блокировку вы увидите в будущем, пока вы помните модели, описанной в этом разделе, в вашем уме, вы обнаружите, что вы меняете суп, не меняя лекарство, и этому очень легко научиться.

У трех основных проблем параллелизма здесь есть решения: упорядоченность, видимость и атомарность.Это позволяет взглянуть на параллелизм со стороны, чтобы у каждого была макроконцепция, но в интервью и реальном бою все зависит от деталей. шаг за шагом рассмотрим детали параллелизма и, кстати, объясните вопросы, которые часто задают интервьюеры

Для получения дополнительной информации, пожалуйста, посетите мой личный блог:dayarch.top/

вопрос души

  1. Обязательно ли существует проблема с несколькими блокировками, блокирующими ресурс?
  2. Когда вам нужно заблокировать сообщество, но не конкретное домашнее хозяйство?
  3. Банковский перевод, два человека переводят друг другу, а другие переводят себе, какая степень детализации блокировки подходит?

инструменты повышения производительности


Рекомендуемое чтение


Добро пожаловать, чтобы продолжать обращать внимание на общественный номер: «Сун Гун И Бин».

  • Передовая технология Java для обмена галантереей
  • Резюме эффективных инструментов | Ответ на «Инструменты»
  • Анализ вопроса интервью и ответ
  • Сбор технических данных | Ответ на «данные»

Узнайте о стеке технологий Java легко и весело, думая о чтении детективных романов, и постепенно разлагайте технические проблемы на основе принципов упрощения сложных проблем, превращения абстрактных проблем в конкретные и графические, а технология постоянно обновляется, пожалуйста, продолжайте платить внимание...