postsharp - threading model library

29
1 © Luxoft Training 2012 PostSharp Threading Pattern Library Андрей Гордиенков [email protected] softblog.violet-tape.ru

Upload: andrey-gordienkov

Post on 18-Jul-2015

3.686 views

Category:

Software


2 download

TRANSCRIPT

Page 1: PostSharp - Threading Model Library

1

© L

uxo

ft T

rain

ing

20

12

PostSharp Threading Pattern Library

Андрей Гордиенков

[email protected]

softblog.violet-tape.ru

Page 2: PostSharp - Threading Model Library

2

Обо мне

Фанат программирования и рассказов о программировании

Ведет свой блог 5+ года: статьи и видео

АОП евангелист

Очень ленив, поэтому ищет пути как писать меньше, а делать больше

Page 3: PostSharp - Threading Model Library

3

Немного из истории языков

Ранние языки строилась вокруг модели памяти

Оперирование переменными, а не адресами памяти

FORTRAN I (1955)

Дальнейшее развитие пошло вокруг модели исполнения

Внедрение методов и подпрограмм

FORTRAN II (1958)

Внедрение областей видимости

ALGOL 60

Объединение концепций

COBOL

Скорее всего первый ООП язык был SIMULA

C++, C# и Java прямые наследники SIMULA

Page 4: PostSharp - Threading Model Library

4

Качества хорошей модели программирования

Адекватные абстракции

Проверяемость

Локальность и разделение ответственности

Детерминизм

Производительность

Page 5: PostSharp - Threading Model Library

5

Threading Pattern Library

Предоставляет высокоуровневый механизм управления моделями

многопоточности для кода.

Проверка времени компиляции и исполнения.

Присутствует в PostSharp Express.

Реализованные модели:

Immutable

Freezable

Synchronized

Reader/Writer Synchronized

Actor

Thread Affine

Thread Unsafe

Page 6: PostSharp - Threading Model Library

6

Необходимые условия работы моделей

Для корректной работы может потребоваться использование специальных

коллекций

AdvisableCollection<T>

AdvisableDictionary<TKey,TValue>

Поддержка концепции агрегации и композиции фреймворком.

[Child]

[Parent]

[Reference]

Page 7: PostSharp - Threading Model Library

7

Пример

[Aggregatable]public class Invoice {

[Child]public readonly AdvisableCollection<InvoiceLine> Lines = new AdvisableCollection<InvoiceLine>();

[Reference]public Customer Customer;

}

[Aggregatable]public class InvoiceLine {

[Reference]public Product Product;

[Parent]public Invoice ParentInvoice { get; private set; }

}

Page 8: PostSharp - Threading Model Library

8

Ключевые идеи PostSharp TPL

Основной фокус направлен на познавательные аспекты программирования

Понятия Immutable, Actor, Freezable, Locking могут относиться к многопоточности

Модели многопоточности относятся к классам, а не к приложению и модулям

Разные модели многопоточности могут сосуществовать в одном приложении

Шаблоны проектирования могут быть реализованы расширением языка, а не

кучей кода

Можно точно определить, что есть валидный код на уровне классов. Исключая

инвариантность.

Использование агрегации/композиции как основы для формализации шаблонов

Page 9: PostSharp - Threading Model Library

9

Immutable

Суть: Объект не может быть изменен после того, как выполнилась вся цепочка

конструкторов.

Подход в целом неадекватен для ООП.

Инициализация объекта часто продолжается после создания объекта.

Никак не регулируется изменяемость объектов принадлежащих классу.

Фиксирование объекта происходит после выполнения последнего

конструктора в цепочке.

Изменятся могут только поля/свойства помеченные [Reference]

Page 10: PostSharp - Threading Model Library

10

Пример

[Immutable]public class Invoice {

public long Id { get; set; }public Invoice(long id) {

Id = id;Items = new AdvisableCollection<Item>();Items.Add(new Item("widget"));

}

[Child]public AdvisableCollection<Item> Items { get; set; }

}

Page 11: PostSharp - Threading Model Library

11

Freezable

Суть: Перед обработкой объекта в других потоках, его надо «заморозить».

Операция не обратимая.

Рабочая модель для идеи «неизменяемых» объектов. В реализации

руководствовались следующим:

Доступ к объекту запрещен для других потоков, пока объект не был заморожен. Даже на

чтение.

После «заморозки» объект не может быть изменен ни при каких обстоятельствах.

Метод Freeze() замораживает также все агрегируемые свойства

«Дети» должны реализовывать модель Immutable или Freezable

Page 12: PostSharp - Threading Model Library

12

Freezable

Применение аспекта внедряет в класс интерфейс IFreezable

public interface IFreezable : IThreadAware {

void Freeze();

}

Page 13: PostSharp - Threading Model Library

13

Пример

[Freezable]public class Invoice {

[Child]public readonly AdvisableCollection<InvoiceLine> Lines = new AdvisableCollection<InvoiceLine>();

[Reference]public Customer Customer;

}

[Freezable]public class InvoiceLine {

[Reference]public Product Product;

[Parent]public Invoice ParentInvoice { get; private set; }

}

Page 14: PostSharp - Threading Model Library

14

Synchronized

Суть: Критические секции класса оборачиваются конструкцией lock(), которая

позволяет обрабатывать (читать/писать) себя только одному потоку

одновременно.

«Классика жанра», самая популярная модель доступа к данным в

многопоточной среде.

Главный подозреваемый при организации deadlock и задержке потоков.

Падение производительности происходит при работе с долгими операциями ввода\вывода

Реализация основана на классе Monitor

Page 15: PostSharp - Threading Model Library

15

Пример

[Synchronized]public class OrderService {

public void Process(int sequence) {Console.WriteLine("sequence {0}", sequence);Console.WriteLine("sleeping for 10s");

Thread.Sleep(new TimeSpan(0, 0, 10));}

}

Page 16: PostSharp - Threading Model Library

16

Reader-Writer Synchronized

Суть: Раздельные уровни блокировки частей кода для чтения и для записи. В

один момент времени чтение позволено многим потокам, запись – только

одному.

Public и Internal методы класса должны быть помечены атрибутами:

[Reader]

[Writer]

[UpgradableReader]

Get/Set автоматически помечаются как [Reader]/[Writer]

Реализация основана на ReaderWriterLockSlim классе

Page 17: PostSharp - Threading Model Library

17

Пример

[ReaderWriterSynchronized]public class Order {

public decimal Amount { get; set; }public decimal Discount { get; set; }[Child]public AdvisableCollection<Item> lines = new AdvisableCollection<Item>();

public decimal AmountAfterDiscount {get { return Amount - Discount; }

}

[Writer]public void Set(decimal amount, decimal discount) {

if (amount < discount) {throw new InvalidOperationException();

}

Amount = amount;Discount = discount;

}}

Page 18: PostSharp - Threading Model Library

18

Actor

Суть: Запросы класса асинхронно перенаправляются в одну очередь исполнения

в которой выполняются по порядку в один поток.

Любой public/internal метод упаковывается в сообщение, которое кладется в

очередь

Класс реализует интерфейс IActor

Реализация основана на классе ConcurrentQueue

Шаблон требует, чтобы все методы относились к следующим категориям:

Ничего не возвращали в результате работы

Были асинхронными. Помечены словом async

public interface IActor : IThreadAware

{

IActorDispatcher Dispatcher { get; }

}

Page 19: PostSharp - Threading Model Library

19

Пример

[Actor]public class AverageCalculator {

private float sum;private int count;

public void AddSample(float n) {count++;sum += n;

}

[Reentrant]public async Task<float> GetAverage() {

return sum / count;}

}

Page 20: PostSharp - Threading Model Library

20

Thread Affine

Суть: Методы класса выполняется только в том потоке, в котором был создан

класс.

Реализация просто запоминает поток создания объекта.

Никаких особенностей =)

Page 21: PostSharp - Threading Model Library

21

Пример

[ThreadAffine]public class OrderService {

public void Process(int sequence) {Console.WriteLine("sequence {0}", sequence);Console.WriteLine("sleeping for 10s");

Thread.Sleep(new TimeSpan(0, 0, 10));}

}

Page 22: PostSharp - Threading Model Library

22

Thread Unsafe

Суть: При одновременном доступе к классу с нескольких потоков, выбрасывается

исключение.

Не рекомендуется к использованию.

Существует только для диагностики проблем многопоточности.

Вызывает исключение, если смена значения происходит в другом потоке.

Реализовано с помощью операции CompareExchange

Page 23: PostSharp - Threading Model Library

23

Пример

[ThreadUnsafe]internal class AverageCalculator {

private float sum;private int count;

public void AddSample(float n) {count++;sum += n;

}

public float GetAverage() {return sum / count;

}}

Page 24: PostSharp - Threading Model Library

24

Особенности использования

Синхронные методы возвращающие результат должны быть помечены

атрибутом [ExplicitlySynchronized]

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

Если точка входа в класс – приватный метод, то его надо обозначить

атрибутом [EntryPoint]

Например, через делегат к приватному методу.

Page 25: PostSharp - Threading Model Library

25

Ограничения при использовании

Ограниченная проверка на этапе сборки

PostSharp проверяет структурную композицию, а не поведение элементов

Блокирующее ожидание в async методах

Все async методы должны быть помечены атрибутом [Reentrant]

Нет асинхронного ожидания

Нет защиты хоста

Не проводились тесты на наличие исключений OutOfMemoryException или

ThreadAbortException в процессе работы.

Page 26: PostSharp - Threading Model Library

26

Написание своей валидации

Фактически любой базовый аспект позволяет переопределить самостоятельно

метод CompileTimeValidate() для валидации на этапе компиляции

[Serializable]public class MethodAttribute : OnMethodBoundaryAspect {

public override bool CompileTimeValidate(MethodBase method) {

}}

[Serializable]public class TypeAspect : TypeLevelAspect {

public override bool CompileTimeValidate(Type type) {

}}

Page 27: PostSharp - Threading Model Library

27

Вопросы

Page 28: PostSharp - Threading Model Library

28

Ссылки

Github https://github.com/VioletTape/PS_TPL_Examples

PostSharp http://www.postsharp.net

Page 29: PostSharp - Threading Model Library

29

© L

uxo

ft T

rain

ing

20

12

Спасибо!

[email protected]

softblog.violet-tape.ru