Составители:
Рубрика:
или не изменять состояние ожидаемого объекта. Так, например, для собы-
тий с ручным сбросом (ManualResetEvent) состояние не меняется, а собы-
тия с автоматическим сбросом и мьютексы (AutoResetEvent, Mutex) пере-
водятся в занятое состояние.
Объекты класса WaitHandle и производных от него, представляя объ-
екты ядра операционной системы, могут быть использованы для межпро-
цессного взаимодействия. Конструкторы производных объектов (событий
и мьютексов) позволяют задать имя объекта ядра, предназначенное для
организации общего доступа к объектам процессами:
using System;
using System.Threading;
namespace TestNamespace {
public class SomeData {
public const int m_queries = 10;
private static int m_counter = 0;
private static Mutex m_mutex = new Mutex();
private static ManualResetEvent m_event =
new ManualResetEvent( false );
public static void Invoke( int no ) {
m_mutex.WaitOne();
m_counter++;
if ( m_counter >= m_queries ) m_event.Set();
m_mutex.ReleaseMutex();
m_event.WaitOne();
}
}
public delegate void AsyncProcCallback( int no );
class TestApp {
public static void Main() {
int i;
WaitHandle[] wh;
AsyncProcCallback apd;
wh = new WaitHandle[ SomeData.m_queries ];
apd = new AsyncProcCallback( SomeData.Invoke );
for ( i = 0; i < SomeData.m_queries; i++ ) wh[i] =
apd.BeginInvoke(i,null,null).AsyncWaitHandle;
WaitHandle.WaitAll( wh );
}
}
}
Разработка параллельных приложений для ОС Windows
267
if ( to > m_size ) to = m_size;
for ( i = 0; i < m_size; i++ ) {
for ( j = 0; j < m_size; j++ ) {
R = 0;
for ( k = from; k < to; k++ ) R += m_A[i,k]*m_B[k,j];
lock ( m_C ) { m_C[i,j] += R; }
}
}
}
Данный пример показывает процедуру потока, осуществляющего по-
полосное умножение матриц с необходимой синхронизацией. Следует за-
метить, что синхронизация доступа требует дополнительных ресурсов
процессора (в данном случае, качественно превышающих затраты на ум-
ножение и сложение двух чисел с плавающей запятой), поэтому целесооб-
разно как можно сильнее сократить число блокировок и время их наложе-
ния. В примере для этого использована промежуточная переменная R, на-
капливающая частичный результат.
Следует особо подчеркнуть, что мониторы и блокировки доступа
только лишь позволяют разработчику реализовать соответствующую син-
хронизацию, но ни в коем случае не осуществляют принудительное огра-
ничение конкурентного обращения к полям и методам объектов. Любой
параллельно выполняющийся фрагмент кода сохраняет полную возмож-
ность обращаться со всеми объектами, независимо от того, связаны они с
какими-либо блокировками или нет. Для синхронизации и блокирования
доступа необходимо, чтобы все участники синхронизации явным образом
использовали критические секции.
Ожидающие объекты
.NET предоставляет базовый класс WaitHandle, служащий для описа-
ния объекта, который находится в одном из двух состояний: занятом или
свободном. На основе этого класса строятся другие классы синхронизиру-
ющих объектов .NET, такие как события (ManualResetEvent и
AutoResetEvent) и мьютексы (Mutex).
Класс WaitHandle является, по сути, оберткой объектов ядра операци-
онной системы, поддерживающих интерфейс синхронизации. Свойство
Handle объекта WaitHandle позволяет установить (или узнать) соответствие
этого объекта .NET с объектом ядра операционной системы.
Существует три метода класса WaitHandle для ожидания освобожде-
ния объекта: метод WaitOne, являющийся методом объекта, и статические
методы WaitAny и WaitAll. Метод WaitOne является оберткой вызова
WaitForSingleObject Win32 API, а методы WaitAny и WaitAll – вызова
WaitForMultipleObjects. Соответственно семантике конкретных объектов
ядра, представленных объектом WaitHandle, методы Wait...могут изменять
266
CIL и системное программирование в Microsoft .NET
266 CIL и системное программирование в Microsoft .NET Разработка параллельных приложений для ОС Windows 267 if ( to > m_size ) to = m_size; или не изменять состояние ожидаемого объекта. Так, например, для собы- for ( i = 0; i < m_size; i++ ) { тий с ручным сбросом (ManualResetEvent) состояние не меняется, а собы- for ( j = 0; j < m_size; j++ ) { тия с автоматическим сбросом и мьютексы (AutoResetEvent, Mutex) пере- R = 0; водятся в занятое состояние. for ( k = from; k < to; k++ ) R += m_A[i,k]*m_B[k,j]; Объекты класса WaitHandle и производных от него, представляя объ- lock ( m_C ) { m_C[i,j] += R; } екты ядра операционной системы, могут быть использованы для межпро- } цессного взаимодействия. Конструкторы производных объектов (событий } и мьютексов) позволяют задать имя объекта ядра, предназначенное для } организации общего доступа к объектам процессами: Данный пример показывает процедуру потока, осуществляющего по- полосное умножение матриц с необходимой синхронизацией. Следует за- using System; метить, что синхронизация доступа требует дополнительных ресурсов using System.Threading; процессора (в данном случае, качественно превышающих затраты на ум- ножение и сложение двух чисел с плавающей запятой), поэтому целесооб- namespace TestNamespace { разно как можно сильнее сократить число блокировок и время их наложе- public class SomeData { ния. В примере для этого использована промежуточная переменная R, на- public const int m_queries = 10; капливающая частичный результат. private static int m_counter = 0; Следует особо подчеркнуть, что мониторы и блокировки доступа private static Mutex m_mutex = new Mutex(); только лишь позволяют разработчику реализовать соответствующую син- private static ManualResetEvent m_event = хронизацию, но ни в коем случае не осуществляют принудительное огра- new ManualResetEvent( false ); ничение конкурентного обращения к полям и методам объектов. Любой public static void Invoke( int no ) { параллельно выполняющийся фрагмент кода сохраняет полную возмож- m_mutex.WaitOne(); ность обращаться со всеми объектами, независимо от того, связаны они с m_counter++; какими-либо блокировками или нет. Для синхронизации и блокирования if ( m_counter >= m_queries ) m_event.Set(); доступа необходимо, чтобы все участники синхронизации явным образом m_mutex.ReleaseMutex(); использовали критические секции. m_event.WaitOne(); Ожидающие объекты } .NET предоставляет базовый класс WaitHandle, служащий для описа- } ния объекта, который находится в одном из двух состояний: занятом или public delegate void AsyncProcCallback( int no ); свободном. На основе этого класса строятся другие классы синхронизиру- class TestApp { ющих объектов .NET, такие как события (ManualResetEvent и public static void Main() { AutoResetEvent) и мьютексы (Mutex). int i; Класс WaitHandle является, по сути, оберткой объектов ядра операци- WaitHandle[] wh; онной системы, поддерживающих интерфейс синхронизации. Свойство AsyncProcCallback apd; Handle объекта WaitHandle позволяет установить (или узнать) соответствие wh = new WaitHandle[ SomeData.m_queries ]; этого объекта .NET с объектом ядра операционной системы. apd = new AsyncProcCallback( SomeData.Invoke ); Существует три метода класса WaitHandle для ожидания освобожде- for ( i = 0; i < SomeData.m_queries; i++ ) wh[i] = ния объекта: метод WaitOne, являющийся методом объекта, и статические apd.BeginInvoke(i,null,null).AsyncWaitHandle; методы WaitAny и WaitAll. Метод WaitOne является оберткой вызова WaitHandle.WaitAll( wh ); WaitForSingleObject Win32 API, а методы WaitAny и WaitAll – вызова } WaitForMultipleObjects. Соответственно семантике конкретных объектов } ядра, представленных объектом WaitHandle, методы Wait...могут изменять }
Страницы
- « первая
- ‹ предыдущая
- …
- 138
- 139
- 140
- 141
- 142
- …
- следующая ›
- последняя »