Составители:
Рубрика:
Методы Allocate... и GetNamedDataSlot позволяют выделить новую
ячейку в TLS памяти (или получить существующую именованную), мето-
ды GetData и SetData позволяют получить или сохранить ссылку на объект
в TLS памяти. Использование TLS памяти в .NET менее удобно и эффек-
тивно, чем в Win32 API, но это связано не с реализацией TLS, а с реализа-
цией потоков:
• Во-первых, возможно размещение данных в TLS памяти только
текущего потока, то есть нельзя положить данные до запуска по-
тока.
• Во-вторых, процедура потока не получает аргументов, то есть
требуется предусмотреть отдельный механизм для передачи дан-
ных в функцию потока, а этот неизбежно реализуемый меха-
низм окажется конкурентом существующей реализации TLS па-
мяти.
• В-третьих, использование TLS памяти в асинхронно вызывае-
мых процедурах может быть ограничено теми соображениями,
что заранее нельзя предугадать поток, который будет выполнять
эту процедуру.
• В-четвертых, использование методов ООП часто позволяет со-
хранить специфичные данные в полях объекта, вообще не при-
бегая к выделению TLS памяти.
7.3.5. Таймеры
.NET предлагает два вида таймеров: один описан в пространстве имен
System.Timers, а другой – в пространстве имен System.Threading.
Таймер пространства имен System.Threading является опечатанным и
предназначен для вызова указанной асинхронной процедуры с заданным
интервалом времени.
Таймер пространства имен System.Timers может быть использован
для создания собственных классов-потомков – в нем вместо процедуры
асинхронного вызова применяется обработка события, с которым может
быть сопоставлено несколько обработчиков. Кроме того, этот таймер мо-
жет вызывать обработку события конкретным потоком, а не произволь-
ным потоком пула:
using System;
using System.Timers;
namespace TestNamespace {
class TestTimer : Timer {
private int m_minimal, m_maximal, m_counter;
public int count { get{ return m_counter – m_minimal; }}
Разработка параллельных приложений для ОС Windows
271
Конечно, аналогичного эффекта можно было бы добиться, просто
используя блокировку (lock или методы класса Monitor) при доступе к объ-
екту. Однако, такой подход потребует наложить блокировку исключитель-
ного доступа при чтении данных, что не эффективно. В обычных услови-
ях вполне допустимо чтение данных несколькими одновременно выпол-
няющимися потоками, что может дать заметное ускорение.
7.3.4.3. Локальная для потока память
Применение локальной для потока памяти в .NET опирается на TLS
память, поддерживаемую операционной системой. Аналогично Win32
API, возможны декларативный и императивный подходы для работы с ло-
кальной для потока памятью.
Декларативный подход сводится к использованию атрибута
ThreadStaticAttribute перед описанием любого статического поля. На-
пример, в следующем фрагменте:
class SomeData {
[ThreadStatic]
public static double xxx;
...
Поле класса SomeData.xxx будет размещено в локальной для каждого
потока памяти.
Императивный подход связан с применением методов
AllocateDataSlot, AllocateNamedDataSlot, GetNamedDataSlot,
FreeNamedDataSlot, GetData и SetData класса Thread. Использование этих
методов очень похоже на использование Tls... функций Win32 API, с той
разницей, что вместо целочисленного индекса в TLS массиве потока (как
это было в Win32 API) используется объект типа LocalDataStoreSlot, кото-
рый выполняет функции прежнего индекса:
class SomeData {
private static LocalDataStoreSlot m_tls = Thread.AllocateDataSlot();
public static void ThreadProc() {
Thread.SetData( m_tls, ... );
...
}
public void Main() {
SomeData sd = new SomeData();
...
// создание и запуск потоков
}
}
270
CIL и системное программирование в Microsoft .NET
270 CIL и системное программирование в Microsoft .NET Разработка параллельных приложений для ОС Windows 271
Конечно, аналогичного эффекта можно было бы добиться, просто Методы Allocate... и GetNamedDataSlot позволяют выделить новую
используя блокировку (lock или методы класса Monitor) при доступе к объ- ячейку в TLS памяти (или получить существующую именованную), мето-
екту. Однако, такой подход потребует наложить блокировку исключитель- ды GetData и SetData позволяют получить или сохранить ссылку на объект
ного доступа при чтении данных, что не эффективно. В обычных услови- в TLS памяти. Использование TLS памяти в .NET менее удобно и эффек-
ях вполне допустимо чтение данных несколькими одновременно выпол- тивно, чем в Win32 API, но это связано не с реализацией TLS, а с реализа-
няющимися потоками, что может дать заметное ускорение. цией потоков:
• Во-первых, возможно размещение данных в TLS памяти только
7.3.4.3. Локальная для потока память текущего потока, то есть нельзя положить данные до запуска по-
Применение локальной для потока памяти в .NET опирается на TLS тока.
память, поддерживаемую операционной системой. Аналогично Win32 • Во-вторых, процедура потока не получает аргументов, то есть
API, возможны декларативный и императивный подходы для работы с ло- требуется предусмотреть отдельный механизм для передачи дан-
кальной для потока памятью. ных в функцию потока, а этот неизбежно реализуемый меха-
Декларативный подход сводится к использованию атрибута низм окажется конкурентом существующей реализации TLS па-
ThreadStaticAttribute перед описанием любого статического поля. На- мяти.
пример, в следующем фрагменте: • В-третьих, использование TLS памяти в асинхронно вызывае-
мых процедурах может быть ограничено теми соображениями,
class SomeData { что заранее нельзя предугадать поток, который будет выполнять
[ThreadStatic] эту процедуру.
public static double xxx; • В-четвертых, использование методов ООП часто позволяет со-
... хранить специфичные данные в полях объекта, вообще не при-
Поле класса SomeData.xxx будет размещено в локальной для каждого бегая к выделению TLS памяти.
потока памяти.
Императивный подход связан с применением методов 7.3.5. Таймеры
AllocateDataSlot, AllocateNamedDataSlot, GetNamedDataSlot, .NET предлагает два вида таймеров: один описан в пространстве имен
FreeNamedDataSlot, GetData и SetData класса Thread. Использование этих System.Timers, а другой – в пространстве имен System.Threading.
методов очень похоже на использование Tls... функций Win32 API, с той Таймер пространства имен System.Threading является опечатанным и
разницей, что вместо целочисленного индекса в TLS массиве потока (как предназначен для вызова указанной асинхронной процедуры с заданным
это было в Win32 API) используется объект типа LocalDataStoreSlot, кото- интервалом времени.
рый выполняет функции прежнего индекса: Таймер пространства имен System.Timers может быть использован
для создания собственных классов-потомков – в нем вместо процедуры
class SomeData { асинхронного вызова применяется обработка события, с которым может
private static LocalDataStoreSlot m_tls = Thread.AllocateDataSlot(); быть сопоставлено несколько обработчиков. Кроме того, этот таймер мо-
public static void ThreadProc() { жет вызывать обработку события конкретным потоком, а не произволь-
Thread.SetData( m_tls, ... ); ным потоком пула:
...
} using System;
public void Main() { using System.Timers;
SomeData sd = new SomeData();
... namespace TestNamespace {
// создание и запуск потоков class TestTimer : Timer {
} private int m_minimal, m_maximal, m_counter;
} public int count { get{ return m_counter – m_minimal; }}
Страницы
- « первая
- ‹ предыдущая
- …
- 140
- 141
- 142
- 143
- 144
- …
- следующая ›
- последняя »
