Составители:
Рубрика:
или не изменять состояние ожидаемого объекта. Так, например, для собы-
тий с ручным сбросом (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
- …
- следующая ›
- последняя »
