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



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


Глава.30 .Гибридные.конструкции.синхронизации.потоков
попытка доступа к любому из них приведет к появлению объекта 
Singleton
. Не-
которые разработчики обходят данную проблему при помощи вложенных классов.
Рассмотрим третий способ создания одиночного объекта 
Singleton
:
internal sealed class Singleton {
private static Singleton s_value = null;
// Закрытый конструктор не дает коду вне данного 
// класса создавать экземпляры
private Singleton() {
// Код инициализации объекта Singleton
}
// Открытый статический метод, возвращающий объект Singleton
// (и создающий его, если это нужно)
public static Singleton GetSingleton() {
if (s_value != null) return s_value;
// Создание нового объекта Singleton и превращение его в корень,
// если этого еще не сделал другой поток
Singleton temp = new Singleton();
Interlocked.CompareExchange(ref s_value, temp, null);
// При потере этого потока второй объект Singleton 
// утилизируется сборщиком мусора
return s_value; // Возвращение ссылки на объект
}
}
При одновременном вызове метода 
GetSingleton
различными потоками в этой 
версии кода может появиться два (и более) объекта 
Singleton
. Однако метод 
Interlocked.CompareExchange
гарантирует публикацию в поле 
s_value
только 
одной ссылки. Любой объект, не превращенный этим полем в корневой, будет 
утилизирован при первой же сборке мусора. Впрочем, в большинстве приложе-
ний практически никогда не возникает ситуация одновременного вызова метода 
GetSingleton
разными потоками, поэтому там вряд ли когда-нибудь появится 
более одного объекта 
Singleton
.
Возможно, вас беспокоит возможность создания множественных объектов 
Singleton
, но данный код имеет массу достоинств. Во-первых, он очень быстро ра-
ботает. Во-вторых, в нем никогда не блокируются потоки. Ведь когда поток из пула 
блокируется на объекте 
Monitor
или на любой другой конструкции синхронизации 
потоков режима ядра, пул порождает еще один поток, чтобы загрузить процессор. 
Выделяется и инициализируется дополнительная память, а все библиотеки полу-
чают уведомление о присоединении нового потока. С методом 
CompareExchange
такого никогда не происходит. Разумеется, данную технику можно использовать 
только при отсутствии побочных эффектов у конструктора.
В FCL существует два типа, реализующие описанные в данном разделе шаблоны 
программирования. Вот как выглядит обобщенный класс 
System.Lazy
(некоторые 
методы не показаны):


879
Блокировка.с.двойной.проверкой
public class Lazy {
public Lazy(Func valueFactory, LazyThreadSafetyMode mode);
public Boolean IsValueCreated { get; }
public T Value { get; }
}
А вот как он работает:
public static void Main() {
// Создание оболочки отложенной инициализации для получения DateTime
Lazy s = new Lazy(
() => DateTime.Now.ToLongTimeString(),
LazyThreadSafetyMode.PublicationOnly);
Console.WriteLine(s.IsValueCreated); // Возвращается false, так как 
// запроса к Value еще не было
Console.WriteLine(s.Value); // Вызывается этот делегат
Console.WriteLine(s.IsValueCreated); // Возвращается true, так как 
// был запрос к Value
Thread.Sleep(10000); // Ждем 10 секунд и снова 
// выводим время
Console.WriteLine(s.Value); // Теперь делегат НЕ вызывается, 
// результат прежний
}
После запуска данного кода я получил:
False
2:40:42 PM
True
2:40:42 PM ß Обратите внимание, 10 секунд прошло, а время осталось прежним
Код сконструировал экземпляр класса 
Lazy
и передал ему один из флагов 
LazyThreadSafetyMode
. Вот как выглядят и что означают данные флаги:
public enum LazyThreadSafetyMode {
None, // Безопасность в отношении потоков не 
// поддерживается (хорошо для GUI-приложений)
ExecutionAndPublication, // Используется блокировка с двойной проверкой
PublicationOnly, // Используется метод Interlocked.CompareExchange
}
В некоторых ситуациях с ограничениями по памяти отсутствует необходимость 
в создании экземпляра класса 
Lazy
. Вместо этого можно воспользоваться статиче-
скими методами класса 
System.Threading.LazyInitializer
. Вот как он выглядит:
public static class LazyInitializer {
// Эти два метода используют Interlocked.CompareExchange
public static T EnsureInitialized(ref T target) where T: class;
public static T EnsureInitialized(
ref T target, Func valueFactory) where T: class;
// Эти два метода передают syncLock в методы Enter и Exit класса Monitor
public static T EnsureInitialized(
продолжение



880
Download 6,27 Mb.

Do'stlaringiz bilan baham:
1   ...   647   648   649   650   651   652   653   654   ...   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