Net framework 5, а также среды Visual Studio 2012 и C#



Download 6,27 Mb.
Pdf ko'rish
bet650/658
Sana12.06.2023
Hajmi6,27 Mb.
#950840
1   ...   646   647   648   649   650   651   652   653   ...   658
Bog'liq
CLR via C Programmirovanie na platforme Microsoft NET Framework 4 5 na yazyke C


Глава.30 .Гибридные.конструкции.синхронизации.потоков
// Открытый статический метод, возвращающий объект Singleton
// (создавая его при необходимости)
public static Singleton GetSingleton() {
// Если объект Singleton уже создан, возвращаем его
if (s_value != null) return s_value;
Monitor.Enter(s_lock); // Если не создан, позволяем одному 
// потоку сделать это
if (s_value == null) {
// Если объекта все еще нет, создаем его
Singleton temp = new Singleton();
// Сохраняем ссылку в переменной s_value (см. обсуждение далее)
Volatile.Write(ref s_value, temp);
}
Monitor.Exit(s_lock);
// Возвращаем ссылку на объект Singleton
return s_value;
}
}
Принцип блокировки с двойной проверкой состоит в том, что при вызове метода 
GetSingleton
быстро проверяется поле 
s_value
, чтобы выяснить, создан ли объ-
ект. При положительном результате проверки метод возвращает ссылку на объект. 
В результате отпадает необходимость в синхронизации потоков, и приложение 
работает очень быстро. Однако если поток, вызвавший метод 
GetSingleton
, не 
обнаруживает объекта, он прибегает к блокированию в рамках синхронизации 
потоков, гарантируя, что созданием объекта будет заниматься только один поток. 
То есть снижение производительности наблюдается только после первого запроса 
к одноэлементному объекту.
Теперь я объясню, почему этот паттерн не работает в Java. В начале метода 
GetSingleton
виртуальная машина Java считывает значение поля 
s_value
в регистр 
процессора и при выполнении второй инструкции 
if
ограничивается запросом 
к этому регистру. В итоге результатом данной проверки всегда является значение 
true
, а это означает, что в создании объекта 
Singleton
принимают участие все по-
токи. Разумеется, это возможно только при условии, что все потоки вызвали метод 
GetSingleton
одновременно, чего в большинстве случаев не происходит. Именно 
поэтому ошибка столько времени оставалась нераспознанной.
В CLR вызов любого метода блокирования означает установку непреодолимого 
барьера на доступ к памяти: вся запись в переменные должна завершиться до этого 
барьера, а любое чтение переменных может начаться только после барьера. Для 
метода 
GetSingleton
это означает, что повторное чтение поля 
s_value
должно 
быть произведено после вызова метода 
Monitor.Enter
; в процессе вызова метода 
значение поля нельзя сохранить в регистре.
Внутри метода 
GetSingleton
вызывается метод 
Volatile.Write
. Предположим, 
что вторая инструкция 
if
содержит следующую строку кода:
s_value = new Singleton(); // В идеале хотелось бы использовать эту команду


877
Блокировка.с.двойной.проверкой
Можно ожидать, что компилятор создаст код, выделяющий память под объект 
Singleton
, вызовет конструктор для инициализации полей данного объекта и при-
своит ссылку на него полю 
s_value
, чтобы это значение увидели другие потоки — это 
называется 
публикацией
(publishing). Однако компилятор может выделить память 
под объект 
Singleton
, назначить ссылку переменной 
s_value
(выполнив публи-
кацию) и только после этого вызвать конструктор. Если в процедуре участвует 
всего один поток, подобное изменение очередности операций не имеет значения. 
Но что произойдет, если после публикации ссылки в поле 
s_value
, но до вызова 
конструктора другой поток вызовет метод 
GetSingleton
? Этот поток обнаружит, что 
значение поля 
s_value
отлично от 
null
и начнет пользоваться объектом 
Singleton

хотя его конструктор еще не закончил работу! Подобную ошибку крайне сложно 
отследить, особенно из-за того, что время ее появления случайно.
Эту проблему решает вызов метода 
Interlocked.Exchange
. Он гарантирует, что 
ссылка из переменной 
temp
будет опубликована в поле 
s_value
только после того, 
как конструктор завершит свою работу. Альтернативным способом решения про-
блемы является пометка поля 
s_value
ключевым словом 
volatile
. Запись в такое 
волатильное (неустойчивое) поле 
s_value
возможна только после завершения 
конструктора. К сожалению, то же самое относится ко всем процедурам чтения во-
латильного поля, а так как никакой необходимости в этом нет, вряд ли стоит идти 
на снижение производительности без полной уверенности в полезности этого.
В начале этого раздела я назвал блокировку с двойной проверкой не особо инте-
ресной. С моей точки зрения, разработчики используют это решение гораздо чаще, 
чем следовало бы. В большинстве случаев оно только снижает производительность. 
Вот гораздо более простая версия класса 
Singleton
с аналогичным предыдущей 
версии поведением, но без блокирования с двойной проверкой:
internal sealed class Singleton {
private static Singleton s_value = new Singleton();
// Закрытый конструктор не дает коду вне данного класса 
// создавать экземпляры
private Singleton() {
// Код инициализации объекта Singleton
}
// Открытый статический метод, возвращающий объект Singleton 
// (и создающий его, если это нужно)
public static Singleton GetSingleton() { return s_value; }
}
Так как CLR автоматически вызывает конструктор класса при первой по-
пытке получить доступ к члену этого класса, при первом запросе потока к методу 
GetSingleton
класса 
Singleton
автоматически создается экземпляр объекта. Более 
того, среда CLR гарантирует безопасность в отношении потоков при вызове кон-
структора класса. Все это уже объяснялось в главе 8. Недостатком такого подхода 
является вызов конструктора типа при первом доступе к любому члену класса. 
То есть если в типе 
Singleton
определить другие статические члены, первая же 


878
Download 6,27 Mb.

Do'stlaringiz bilan baham:
1   ...   646   647   648   649   650   651   652   653   ...   658




Ma'lumotlar bazasi mualliflik huquqi bilan himoyalangan ©hozir.org 2024
ma'muriyatiga murojaat qiling

kiriting | ro'yxatdan o'tish
    Bosh sahifa
юртда тантана
Боғда битган
Бугун юртда
Эшитганлар жилманглар
Эшитмадим деманглар
битган бодомлар
Yangiariq tumani
qitish marakazi
Raqamli texnologiyalar
ilishida muhokamadan
tasdiqqa tavsiya
tavsiya etilgan
iqtisodiyot kafedrasi
steiermarkischen landesregierung
asarlaringizni yuboring
o'zingizning asarlaringizni
Iltimos faqat
faqat o'zingizning
steierm rkischen
landesregierung fachabteilung
rkischen landesregierung
hamshira loyihasi
loyihasi mavsum
faolyatining oqibatlari
asosiy adabiyotlar
fakulteti ahborot
ahborot havfsizligi
havfsizligi kafedrasi
fanidan bo’yicha
fakulteti iqtisodiyot
boshqaruv fakulteti
chiqarishda boshqaruv
ishlab chiqarishda
iqtisodiyot fakultet
multiservis tarmoqlari
fanidan asosiy
Uzbek fanidan
mavzulari potok
asosidagi multiservis
'aliyyil a'ziym
billahil 'aliyyil
illaa billahil
quvvata illaa
falah' deganida
Kompyuter savodxonligi
bo’yicha mustaqil
'alal falah'
Hayya 'alal
'alas soloh
Hayya 'alas
mavsum boyicha


yuklab olish