Двойная проверка на null

Тот кто изучал исходники CLR, или писал многопоточный код много раз видел подобный код:
if (a == null) lock (this) {
if (a == null) a = new A();
}
Лично я, когда увидел его впервые, был удивлен двойной проверкой. Но, подумав, понял зачем это надо. Ведь пока мы ждали блокировки (это могло быть достаточно длинное ожидание, в случае, если объектом this владел кто-то другой), кто-то мог уже изменить переменную a.
Сегодня, в одном весьма нетривиальном коде, мне пришлось еще одну вариацию написать:
if (a == null)
Interlocked.CompareExchange(ref a, new A(), null);
Суть почти та же, что и в предыдущем примере. Почти, потому что есть несколько отличий:
  1. Нет блокировки потоков (все помнят что функции Interlocked работают гораздо быстрее, чем использование Monitor-ов).
  2. Объект A может создается после первой проверки, но до второй. Это означает, что он может создаваться лишний раз и потому такой вариант не подходит, если это создание имеет побочный эффект.
Второй вариант очень полезен именно тем, что исключает блокировку потоков (в том числе и взаимную блокировку). Потому в случаях, когда стоимость создания объекта A относительно невелика, я бы отдавал предпочтение именно ему.

Коментарі

Популярні дописи з цього блогу

Посчитать количество вхождений каждого слова в текстовом файле

Українська мова