Составители:
Рубрика:
int i,j,k, from, to;
from = ( m_stripused++ ) * m_stripsize;
to = from + m_stripsize;
...
Здесь потенциально возможна ситуация, когда несколько потоков
одновременно начнут выполнять этот код и получат идентичные номера
полос. В этом месте самым эффективным было бы использование атомар-
ных операций для увеличения значения поля m_stripused. Для этого фраг-
мент надо переписать:
public static void ThreadProc()
{
int i,j,k, from, to;
from = (Interlocked.Increment(ref m_stripused) – 1 ) * m_stripsize;
to = from + m_stripsize;
...
7.3.4.2. Синхронизация потоков
Основные средства взаимной синхронизации потоков в .NET обла-
дают заметным сходством со средствами операционной системы. Среди
них можно выделить:
• Мониторы, близкие к критическим секциям Win32 API.
• События и мьютексы, имеющие соответствующие аналоги сре-
ди объектов ядра.
• Плюс дополнительный достаточно универсальный синхронизи-
рующий объект, обеспечивающий множественный доступ пото-
ков по чтению и исключительный – по записи.
Последний синхронизирующий объект ReaderWriterLock закрывает
очень типичный класс задач синхронизации – для многих объектов явля-
ется совершенно корректным конкурентный доступ для чтения и требу-
ются исключительные права для изменения данных. Причина в том, что
изменение сложных объектов осуществляется не атомарно, поэтому во
время постепенного внесения изменений объект кратковременно пребы-
вает в некорректном состоянии – при этом должен быть исключен
не только доступ других потоков, пытающихся внести изменения, но даже
потоков, осуществляющих чтение.
Мониторы
Мониторы в .NET являются аналогами критических секций в Win32
API. Использование мониторов достаточно эффективно (это один из са-
мых эффективных механизмов) и удобно настолько, что в .NET был пре-
дусмотрен механизм, который позволяет использовать практически лю-
бой объект, хранящийся в управляемой куче, для синхронизации доступа.
Разработка параллельных приложений для ОС Windows
261
public delegate void AsyncProcCallback ( GreetingData gd );
class TestApp {
public static void Main() {
GreetingData gd = new GreetingData( “Hello!!!” );
AsyncProcCallback apd = new AsyncProcCallback(
GreetingData.Invoke );
IAsyncResult ar = apd.BeginInvoke( gd, null, null );
ar.AsyncWaitHandle.WaitOne();
}
}
}
Данный пример иллюстрирует вызов асинхронной процедуры с ис-
пользованием метода BeginInvoke и альтернативный механизм ожидания
завершения – с использованием внутреннего объекта AsyncWaitHandle
(класса WaitHandle), благодаря которому, собственно говоря, становится
возможен вызов асинхронной процедуры, обслуживающей завершение
обработки данной процедуры.
В этом смысле асинхронный вызов процедур с помощью BeginInvoke
очень близок к обработке асинхронных операций ввода-вывода.
7.3.4. Синхронизация и изоляция потоков
Проблемы, встающие перед разработчиками многопоточных прило-
жений .NET, очень похожи на проблемы разработчиков приложений Win32
API. Соответственно, .NET предоставляет в значительной мере близкий
набор средств взаимодействия потоков и их взаимной синхронизации.
К этим средствам относятся атомарные операции, локальная для по-
тока память, синхронизирующие примитивы и таймеры. Их применение в
основе своей похоже на применение аналогичных средств API.
7.3.4.1. Атомарные операции
Платформа .NET предоставляет, аналогично базовой операционной
системе Windows, набор некоторых основных операций над целыми числами
(int и long), которые могут выполняться атомарно. Для этого предусмотре-
ны четыре статических метода класса System.Threading.Interlocked, а имен-
но Increment, Decrement, Exchange и CompareExchange. Применение этих мето-
дов аналогично соответствующим Interlocked... процедурам Win32 API.
Возвращаясь к примеру использования потоков для умножения мат-
риц, можно выделить один момент, требующий исправления: самое нача-
ло процедуры потока, там, где определяется номер полосы:
public static void ThreadProc()
{
260
CIL и системное программирование в Microsoft .NET
260 CIL и системное программирование в Microsoft .NET Разработка параллельных приложений для ОС Windows 261 public delegate void AsyncProcCallback ( GreetingData gd ); int i,j,k, from, to; class TestApp { from = ( m_stripused++ ) * m_stripsize; public static void Main() { to = from + m_stripsize; GreetingData gd = new GreetingData( “Hello!!!” ); ... AsyncProcCallback apd = new AsyncProcCallback( Здесь потенциально возможна ситуация, когда несколько потоков GreetingData.Invoke ); одновременно начнут выполнять этот код и получат идентичные номера IAsyncResult ar = apd.BeginInvoke( gd, null, null ); полос. В этом месте самым эффективным было бы использование атомар- ar.AsyncWaitHandle.WaitOne(); ных операций для увеличения значения поля m_stripused. Для этого фраг- } мент надо переписать: } } public static void ThreadProc() Данный пример иллюстрирует вызов асинхронной процедуры с ис- { пользованием метода BeginInvoke и альтернативный механизм ожидания int i,j,k, from, to; завершения – с использованием внутреннего объекта AsyncWaitHandle from = (Interlocked.Increment(ref m_stripused) – 1 ) * m_stripsize; (класса WaitHandle), благодаря которому, собственно говоря, становится to = from + m_stripsize; возможен вызов асинхронной процедуры, обслуживающей завершение ... обработки данной процедуры. В этом смысле асинхронный вызов процедур с помощью BeginInvoke 7.3.4.2. Синхронизация потоков очень близок к обработке асинхронных операций ввода-вывода. Основные средства взаимной синхронизации потоков в .NET обла- дают заметным сходством со средствами операционной системы. Среди 7.3.4. Синхронизация и изоляция потоков них можно выделить: Проблемы, встающие перед разработчиками многопоточных прило- • Мониторы, близкие к критическим секциям Win32 API. жений .NET, очень похожи на проблемы разработчиков приложений Win32 • События и мьютексы, имеющие соответствующие аналоги сре- API. Соответственно, .NET предоставляет в значительной мере близкий ди объектов ядра. набор средств взаимодействия потоков и их взаимной синхронизации. • Плюс дополнительный достаточно универсальный синхронизи- К этим средствам относятся атомарные операции, локальная для по- рующий объект, обеспечивающий множественный доступ пото- тока память, синхронизирующие примитивы и таймеры. Их применение в ков по чтению и исключительный – по записи. основе своей похоже на применение аналогичных средств API. Последний синхронизирующий объект ReaderWriterLock закрывает очень типичный класс задач синхронизации – для многих объектов явля- 7.3.4.1. Атомарные операции ется совершенно корректным конкурентный доступ для чтения и требу- Платформа .NET предоставляет, аналогично базовой операционной ются исключительные права для изменения данных. Причина в том, что системе Windows, набор некоторых основных операций над целыми числами изменение сложных объектов осуществляется не атомарно, поэтому во (int и long), которые могут выполняться атомарно. Для этого предусмотре- время постепенного внесения изменений объект кратковременно пребы- ны четыре статических метода класса System.Threading.Interlocked, а имен- вает в некорректном состоянии – при этом должен быть исключен но Increment, Decrement, Exchange и CompareExchange. Применение этих мето- не только доступ других потоков, пытающихся внести изменения, но даже дов аналогично соответствующим Interlocked... процедурам Win32 API. потоков, осуществляющих чтение. Возвращаясь к примеру использования потоков для умножения мат- Мониторы риц, можно выделить один момент, требующий исправления: самое нача- Мониторы в .NET являются аналогами критических секций в Win32 ло процедуры потока, там, где определяется номер полосы: API. Использование мониторов достаточно эффективно (это один из са- мых эффективных механизмов) и удобно настолько, что в .NET был пре- public static void ThreadProc() дусмотрен механизм, который позволяет использовать практически лю- { бой объект, хранящийся в управляемой куче, для синхронизации доступа.
Страницы
- « первая
- ‹ предыдущая
- …
- 135
- 136
- 137
- 138
- 139
- …
- следующая ›
- последняя »