Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Разделение данных между потоками






Если некий метод запускается в нескольких потоках, только локальные переменные метода будут уникальными для потока. Поля объектов по умолчанию разделяются между всеми потоками. В пространстве имён System определён атрибут [ThreadStatic], применяемый к статическим полям. Если поле помечено таким атрибутом, то каждый поток будет содержать свой экземпляр поля. Для [ThreadStatic]-полей не рекомендуется делать инициализацию при объявлении, так как код инициализации выполнится только в одном потоке.

public class SomeClass

{

public static int SharedField = 25;

 

[ThreadStatic]

public static int NonSharedField;

}

Для создания неразделяемых статических полей можно использовать тип ThreadLocal< T>. Перегруженный конструктор ThreadLocal< T> принимает функцию инициализации поля. Значение поля хранится в свойстве Value.

public class Slot

{

private static readonly Random rnd = new Random();

 

private static int Shared = 25;

private static ThreadLocal< int> NonShared =

new ThreadLocal< int> (() => rnd.Next(1, 20));

 

public static void PrintData()

{

Console.WriteLine(" Thread: {0} Shared: {1} NonShared: {2}",

Thread.CurrentThread.Name,

Shared, NonShared.Value);

}

}

 

public class MainClass

{

public static void Main()

{

// для тестирования запускаем три потока

new Thread(Slot.PrintData) {Name = " First" }.Start();

new Thread(Slot.PrintData) {Name = " Second" }.Start();

new Thread(Slot.PrintData) {Name = " Third" }.Start();

Console.ReadLine();

}

}

Отметим, что класс Thread имеет статические методы AllocateDataSlot(), AllocateNamedDataSlot(), GetNamedDataSlot(), FreeNamedDataSlot(), GetData(), SetData(), которые предназначены для работы с локальными хранилищами данных потока. Эти локальные хранилища могут рассматриваться как альтернатива неразделяемым статическим полям.

Распространённый шаблон при разработке многопоточных приложений – неизменяемый объект (immutable object). После создания такой объект допускает только чтение своих полей, но не запись. Приведём пример класса, объекты которого являются неизменяемыми:

public class ProgressStatus

{

public readonly int PercentComplete;

public readonly string StatusMessage;

 

public ProgressStatus(int percentComplete, string statusMessage)

{

PercentComplete = percentComplete;

StatusMessage = statusMessage;

}

}

Достоинство неизменяемых объектов с точки зрения многопоточности заключается в том, что работа с ними требует коротких блокировок, обычно обрамляющих операции присваивания объектов:

public class WorkWithImmutable

{

private readonly object _locker = new object();

private ProgressStatus _status;

 

public void SetFields()

{

// создаём и настраиваем временный объект

var status = new ProgressStatus(50, " Working on it");

 

// переносим информацию, используя короткую блокировку

lock (_locker) _status = status;

}

 

public void ReadInfo()

{

// используя короткую блокировку, создаём временную копию

ProgressStatus statusCopy;

lock (_locker) statusCopy = _status;

 

// работаем с копией

int pc = statusCopy.PercentComplete;

string msg = statusCopy.StatusMessage;

}

}






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.