Введение в разработку многопоточных приложений
description
Transcript of Введение в разработку многопоточных приложений
![Page 1: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/1.jpg)
Введение в разработку многопоточных приложений
Дмитрий Костиков Ведущий разработчик C#
31 октября 2012 года
![Page 2: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/2.jpg)
2/62
![Page 3: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/3.jpg)
Поморгаем int main() { while(true) { EnableLedOne(); DisableLedOne(); } }
3/62
![Page 4: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/4.jpg)
Поморгаем int Delay(int ms) { for(int i = 0; i < ms * k ; i++){} } int main() { while(true) { EnableLedOne(); Delay(300); DisableLedOne(); Delay(900); } } 4/62
![Page 5: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/5.jpg)
Одна лампочка
300 900 300 900 300
t(мс)
5/62
![Page 6: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/6.jpg)
6/62
![Page 7: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/7.jpg)
Две лампочки
7/62
300 900 300 900 300
t(мс)
250 750 250 250 750 750
![Page 8: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/8.jpg)
Две лампочки
300 900 300 900 300
t(мс)
250 750 250 250 750 750
50 мс
8/62
![Page 9: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/9.jpg)
Очередь заданий Task1, через 50мс Task2, через 100мс
Task1, сейчас Task2, через 50мс
Task2, сейчас
t(мс)
0 100 50
9/62
![Page 10: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/10.jpg)
Поморгаем с планировщиком void EnableLedOneTask() { EnableLedOne(); RegisterDelayedTask(DisableLedOneTask, 300); } void DisableLedOneTask() { DisableLedOne(); RegisterDelayedTask(EnableLedOneTask, 900); } int main() { RegisterDelayedTask(EnableLedOneTask, 0); RegisterDelayedTask(EnableLedTwoTask, 0); while(true) { Delay(50); ExecuteTaskByTime(); } }
10/62
![Page 11: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/11.jpg)
Sleep void LedOne () { while(true) { EnableLedOne(); Sleep(300); DisableLedOne(); Sleep(600); } }
11/62
![Page 12: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/12.jpg)
Sleep void LedOneThread() { B202 while(true) B203 { B204 EnableLedOne(); B205 Sleep(300); B207 DisableLedOne(); B208 Sleep(600); B209 } }
12/62
![Page 13: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/13.jpg)
Sleep void LedOneThread() { int i = GetOnTime(); int j = GetOffTime(); while(true) { EnableLedOne(); Sleep(i); DisableLedOne(); Sleep(j); } }
13/62
![Page 14: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/14.jpg)
Стек и регистры
j
Регистры
Стек
i
14/62
![Page 15: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/15.jpg)
Стек и регистры
Стек
h j
15/62
Регистры
g
![Page 16: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/16.jpg)
Стеки и регистры
Регистры
i
j
Стек потока 1
i
16/62
![Page 17: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/17.jpg)
Стеки и регистры
Регистры
Стек потока 2
g
h j
Стек потока 1
i g
17/62
![Page 18: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/18.jpg)
Поток Физически – процедура потока, служебные
данные и стек
Логически – виртуальный процессор
18/62
![Page 19: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/19.jpg)
Типы многопоточности
Sleep()
Sleep()
Поток 1 Поток 2
t t
19/62
![Page 20: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/20.jpg)
Типы многопоточности
Кванты
Sleep()
Поток 2
t t
Квант кончился
Квант кончился
20/62
Поток 1
![Page 21: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/21.jpg)
Создание потоков .NET: class Thread WinAPI: CreateThread/TerminateThread
static void Main(string[] args) { Thread thread = new Thread(DoA); thread.Start(); } static void DoA() { … }
21/62
![Page 22: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/22.jpg)
Пул потоков WinAPI: QueueUserWorkItem .NET: class ThreadPool
static void Main(string[] args) { ThreadPool.QueueUserWorkItem(DoA); } static void DoA(object state) { }
22/62
![Page 23: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/23.jpg)
23/62
![Page 24: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/24.jpg)
24/62
![Page 25: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/25.jpg)
GUI void OnClick() { ThreadPool.QueueUserWorkItem(DoA); } void DoA(object state) { resultTextBox.Text = ComputeSmth(); }
25/62
![Page 26: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/26.jpg)
GUI
Очередь сообщений
Поток окна
Перерисуй окно
Кликнули мышкой
26/62
![Page 27: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/27.jpg)
GUI
Очередь сообщений
Поток окна
Перерисуй окно
Кликнули мышкой
Обработай окончание
вычисления
27/62
![Page 28: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/28.jpg)
GUI static void DoA(object state) { _result = ComputeSmth(); resultTextBox.BeginInvoke(SetResult); } static void SetResult (object state) { resultTextBox.Text = _result; } 28/62
![Page 29: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/29.jpg)
29/62
![Page 30: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/30.jpg)
Проблемы многопоточности Проблемы корректности
Проблемы живучести
30/62
![Page 31: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/31.jpg)
Состояние гонки _i++; MOV EAX , [_ i ] INC EAX MOV [ _i ] , EAX
31/62
![Page 32: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/32.jpg)
«Одновременное» выполнение Поток 1
MOV EAX , [ i ]
INC EAX
MOV [ i ] , EAX
Поток 2
MOV EAX , [ i ]
INC EAX
MOV [ i ] , EAX
t
32/62
![Page 33: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/33.jpg)
Многопроцессорная машина
Процессор 1 Процессор 2
Память
Кэш 1 Кэш 2
i = 2 i = 2 i = 3 i = 3
33/62
i = 2 i = 2 i = 3 i = 3
![Page 34: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/34.jpg)
Многопроцессорная машина
Процессор 1 Процессор 2
Память
Кэш 1 Кэш 2
i = 2 i = 2
i = 2 i = 2 i = 3 i = 3
i = 3 i = 3
Когерентность кэша
34/62
![Page 35: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/35.jpg)
Последовательное выполнение Поток 1
Enter() MOV EAX , [ i ] INC EAX MOV [ i ] , EAX Exit()
Поток 2
Enter() INC EAX MOV EAX , [ i ] MOV [ i ] , EAX t
35/62
![Page 36: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/36.jpg)
Критический регион
… EnterCriticalRegion() _i++; LeaveCriticalRegion() …
36/62
![Page 37: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/37.jpg)
Критический регион int taken = 0; void EnterCriticalRegion() { while(taken != 0) {} taken = 1; } void LeaveCriticalRegion() { taken = 0; }
37/62
![Page 38: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/38.jpg)
38/62
![Page 39: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/39.jpg)
Строгое чередование const int N = 2; int turn = 0; void EnterCriticalRegion (int i) { while (turn != i ) {} } void LeaveCriticalRegion (int i) { turn = (i + 1) % N; }
39/62
![Page 40: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/40.jpg)
Алгоритм Петерсона (1981) bool flags[2]; int turn = 0; void EnterCriticalRegion (int i) { flags [ i ] = true ; turn = 1 - i ; while ( flags[1 - i] && turn != i ) {} } void LeaveCriticalRegion (int i) { flags [i] = false; }
40/62
![Page 41: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/41.jpg)
CAS long CompareExchange(long *Destination, long Exchange, long Comparand); int taken = 0; void EnterCriticalRegion() { while( CompareExchange((&taken ,1 , 0)) {} } void LeaveCriticalRegion() { taken = 0; }
41/62
![Page 42: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/42.jpg)
Interlocked Interlocked.Increment(ref _i);
42/62
![Page 43: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/43.jpg)
Mutex static Mutex _mutex = new Mutex();
static void DoA(object state)
{
_mutex.WaitOne();
_i++;
_mutex.ReleaseMutex();
}
43/62
![Page 44: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/44.jpg)
Monitor void EnterCriticalRegion()
{
for(int i = 0; i < 1000 &&
! CompareExchange((&taken ,1 , 0)) ; i++)
{}
if(taken == 0)
{
_mutex.WaitOne();
}
}
44/62
![Page 45: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/45.jpg)
Monitor private static object _lockObject; static void DoA(object state) { lock(_lockObject) { ThreadUnsafeOperation(); } } WinAPI: EnterCriticalSection/LeaveCriticalSection
45/62
![Page 46: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/46.jpg)
Неблокирующая синхронизация
46/62
![Page 47: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/47.jpg)
Фокус flags[i] = true;
turn = 1 - i;
while (flags[1 - i] && turn != i)
{ }
47/62
![Page 48: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/48.jpg)
Фокус flags[i] = true;
turn = 1 - i;
int tmp1 = flags[1 - i]
int tmp2 = turn != I
…
48/62
![Page 49: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/49.jpg)
Фокус flags[i] = true;
int tmp1 = flags[1 - i]
…
49/62
![Page 50: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/50.jpg)
Фокус
50/62
CPU1
flags[0] = true; int tmp1 = flags[1] …
CPU2
flags[1] = true; int tmp1 = flags[0] …
![Page 51: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/51.jpg)
Фокус
CPU1
flags[0] = true; int tmp1 = flags[1] …
CPU2
flags[1] = true; int tmp1 = flags[0] …
51/62
![Page 52: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/52.jpg)
Многопроцессорная машина
Процессор 1 Процессор 2
Память
Кэш 1 Кэш 2 flags[0] = true
flags[1] = true
flags[0]=0 flags[1]=0
flags[0]=0 flags[1]=0
52/62
![Page 53: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/53.jpg)
Фокус int tmp1 = flags[1 - i]
flags[i] = true;
…
53/62
![Page 54: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/54.jpg)
Memory barrier flags[i] = true;
Thread.MemoryBarrier();
int tmp1 = flags[1 - i]
…
54/62
![Page 55: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/55.jpg)
Lock flags[i] = true; turn = 1 - i; lock (_object) { while (flags[1 - i] && turn != i) { } }
55/62
![Page 56: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/56.jpg)
56/62
![Page 57: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/57.jpg)
Deadlock public static void Transfer(BankAccount a, BankAccount b, decimal amount) { lock (a) { if (a.m_balance < amount) throw new Exception("Insufficient funds."); lock (b) { a.m_balance -= amount; b.m_balance += amount; } } } 57/62
![Page 58: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/58.jpg)
Deadlock
Поток 1
Поток 2
Lock(счет1)
Lock(счет2)
Lock(счет2)
Lock(счет1) t
58/62
![Page 59: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/59.jpg)
Банковский алгоритм public static void Transfer(BankAccount a, BankAccount b, decimal amount) { LockManager.LockAccounts(a, b) if (a.m_balance < amount) throw new Exception("Insufficient funds."); a.m_balance -= amount; b.m_balance += amount; } 59/62
![Page 60: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/60.jpg)
Сортировка
Поток 1
Поток 2
Lock(счет1) Lock(счет2)
Lock(счет1) Lock(счет2) t
60/62
![Page 61: Введение в разработку многопоточных приложений](https://reader031.fdocuments.net/reader031/viewer/2022020116/557ed821d8b42a815a8b4ad8/html5/thumbnails/61.jpg)
Что почитать Concurrent Programming on Windows
(Joe Duffy)
http://www.albahari.com/threading/
CLR via C# (Jeffrey Richter)
http://habrahabr.ru/users/rumatavz
Memory Barriers: a Hardware View for Software Hackers
61/62