Составители:
Рубрика:
Методы 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
- …
- следующая ›
- последняя »