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



Download 6,27 Mb.
Pdf ko'rish
bet615/658
Sana12.06.2023
Hajmi6,27 Mb.
#950840
1   ...   611   612   613   614   615   616   617   618   ...   658
Bog'liq
CLR via C Programmirovanie na platforme Microsoft NET Framework 4 5 na yazyke C


Глава.29 .Примитивные.конструкции.синхронизации.потоков
Метод 
Main
в этом фрагменте кода создает новый поток, исполняющий метод 
Worker
, который считает по возрастающей, пока не получит команду остановиться. 
Метод 
Main
позволяет потоку метода 
Worker
работать 5 секунд, а затем останав-
ливает его, присваивая статическому полю 
Boolean
значение 
true
. В этот момент 
поток метода 
Worker
должен вывести результат счета, после чего он завершится. 
Метод 
Main
ждет завершения метода 
Worker
, вызывает метод 
Join
, после чего по-
ток метода 
Main
возвращает управление, заставляя весь процесс прекратить работу.
Выглядит просто, не так ли? Но программа скрывает потенциальные проблемы 
из-за возможных оптимизаций. При компиляции метода 
Worker
компилятор обна-
руживает, что переменная 
s_stopWorker
может принимать значение 
true
или 
false

но внутри метода это значение никогда не меняется. Поэтому компилятор может 
создать код, заранее проверяющий состояние переменной 
s_stopWorker
. Если она 
имеет значение 
true
, выводится результат 
"Worker: stopped when x=0"
. В про-
тивном случае компилятор создает код, входящий в бесконечный цикл и бесконечно 
увеличивающий значение переменной 
x
. При этом оптимизация заставляет цикл 
работать крайне быстро, так как проверка переменной 
s_stopWorker
осуществляется 
перед циклом, а проверки переменной на каждой итерации цикла не происходит.
Если вы хотите посмотреть, как это работает, поместите код в файл с расширени-
ем 
cs
и скомпилируйте его с ключами 
platform:x86
и 
/optimize+
компилятора C#. 
Запустите полученный исполняемый файл и вы убедитесь, что программа работает 
бесконечно. Обратите внимание, что вам нужен JIT-компилятор для платформы 
x86, который совершеннее компиляторов x64 и IA64, а значит, обеспечивает более 
полную оптимизацию. Остальные JIT-компиляторы не выполняют оптимизацию 
столь тщательно, поэтому после их работы программа успешно завершится. Это 
подчеркивает еще один интересный аспект: итоговое поведение вашей программы 
зависит от множества факторов, в частности от выбранной версии компилятора и ис-
пользуемых ключей, от выбранного JIT-компилятора, от процессора, который будет 
выполнять код. Кроме того, программа не станет работать бесконечно, если запустить 
ее в отладчике, так как отладчик заставляет JIT-компилятор ограничиться неопти-
мизированным кодом, который проще поддается выполнению в пошаговом режиме.
Рассмотрим другой пример, в котором пара потоков осуществляет доступ к двум 
полям:
internal sealed class ThreadsSharingData {
private Int32 m_flag = 0;
private Int32 m_value = 0;
// Этот метод исполняется одним потоком
public void Thread1() {
// ПРИМЕЧАНИЕ. Они могут выполняться в обратном порядке
m_value = 5;
m_flag = 1;
}
// Этот метод исполняется другим потоком


829
Конструкции.пользовательского.режима
public void Thread2() {
// ПРИМЕЧАНИЕ. Поле m_value может быть прочитано раньше, чем m_flag
if (m_flag == 1)
Console.WriteLine(m_value);
}
}
В данном случае проблема в том, что компиляторы и процессор могут оттрансли-
ровать код таким образом, что две строки в методе 
Thread1
поменяются местами. 
Разумеется, это не изменит предназначения метода. Метод должен получить зна-
чение 5 в переменной 
m_value
и значение 1 в переменной 
m_flag
. С точки зрения 
однопоточного приложения порядок выполнения строк кода не имеет значения. 
Если же поменять указанные строки местами, другой поток, выполняющий метод 
Thread2

может
обнаружить, что переменная 
m_flag
имеет значение 1, и выведет 
значение 0.
Рассмотрим этот код с другой точки зрения. Предположим, что код метода 
Thread1
выполняется так, как 
предусмотрено программой
(то есть так, как он на-
писан). Обрабатывая код метода 
Thread2
, компилятор должен сгенерировать код, 
читающий значения переменных 
m_flag
и 
m_value
из оперативной памяти в ре-
гистры процессора. И возможно, что память первой выдаст значение переменной 
m_value
, равное 0. Затем может выполниться метод 
Thread1
, меняющий значение 
переменной 
m_value
на 5, а переменной 
m_flag
— на 1. Но регистр процессора ме-
тода 
Thread2
не видит, что значение переменной 
m_value
было изменено другим 
потоком на 5. После этого из оперативной памяти в регистре процессора может 
быть считано значение переменной 
m_flag
, ставшее равным 1. В результате метод 
Thread2
снова выведет значение 0.
Все эти крайне неприятные события, скорее всего, приведут к проблемам в окон-
чательной, а не в отладочной версии программы. В результате задача выявления 
проблемы и исправления кода становится нетривиальной. Поэтому сейчас давайте 
поговорим о том, как исправить код.
Класс 
System.Threading.Volatile
содержит два статических метода, которые 
выглядят следующим образом
1
:
public sealed class Volatile {
public static void Write(ref Int32 location, Int32 value);
public static Int32 Read(ref Int32 location);
}
Это специальные методы, отключающие оптимизации, обычно выполняемые 
компилятором C#, JIT-компилятором и собственно процессором. Вот как они 
работают:
1
Существуют также перегруженные версии методов VolatileRead и VolatileWrite, рабо-
тающие с типами: Boolean, (S)Byte, (U)Int16, UInt32, (U)Int64, (U)IntPtr, Single, Double 
и T, где T — обобщенный тип с ограничением 'class' (ссылочные типы).


830
Download 6,27 Mb.

Do'stlaringiz bilan baham:
1   ...   611   612   613   614   615   616   617   618   ...   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