Last active
March 29, 2026 18:45
-
-
Save sunmeat/b8f3cff7c5fcf49cf86e838a88cebebd to your computer and use it in GitHub Desktop.
WaitOne, volatile
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System.Text; | |
| class Program | |
| { | |
| static volatile bool duckRoasted = false; // volatile гарантує, що зміни змінної, зроблені одним потоком, одразу стануть видимими іншим потокам | |
| // без volatile компілятор і процесор можуть оптимізувати код так, що один потік (який лайкає пости) читатиме застаріле значення duckRoasted, закешоване в регістрах процесора або кеші ядра CPU | |
| // це може призвести до ситуації, коли duckRoasted уже встановлено в true у roastDuck(), але likeSocialMediaPosts() продовжує працювати безкінечно, не помічаючи зміни | |
| // без volatile компілятор або процесор можуть переставити інструкції місцями, наприклад, записати duckRoasted = true; до виведення "Качка готова!", що може призвести до некоректного порядку подій | |
| // volatile – це простий спосіб уникнути проблем із кешуванням змінної між потоками | |
| // перший потоковий метод приготування качки | |
| static void roastDuck(object? param) | |
| { | |
| Console.WriteLine("Запікаю качку... Вона в духовці."); | |
| Thread.Sleep(7000); // запікання за рецептом займає 7 секунд :) | |
| Console.WriteLine("Качка готова! Запах неймовірний!"); | |
| duckRoasted = true; | |
| (param as ManualResetEvent)?.Set(); // цей рядок означає: | |
| // - перетворює параметр param (типу object) на тип ManualResetEvent за допомогою оператора as. | |
| // якщо перетворення успішне (тобто param є ManualResetEventом), викликається метод Set(), який сигналізує, що подія відбулася, дозволяючи іншим потокам продовжити роботу. | |
| // оператор ?. забезпечує безпечний виклик: якщо param не є ManualResetEvent (тобто null після as), метод Set() не викликається, уникаючи помилки. | |
| } | |
| // другий потоковий метод для лайкання постів у соцмережах | |
| static void likeSocialMediaPosts() | |
| { | |
| int x = 0; | |
| while (!duckRoasted) | |
| { | |
| Console.WriteLine($"Лайкаю рілс #{++x} в інсті..."); | |
| Thread.Sleep(1000); // лайк із затримкою в 1 секунду | |
| } | |
| } | |
| static void Main() | |
| { | |
| Console.OutputEncoding = Encoding.UTF8; | |
| // 1. основний потік чекає результат безкінечно | |
| Thread t1 = new(roastDuck); | |
| t1.Start("apples"); | |
| Thread t2 = new Thread(likeSocialMediaPosts); | |
| t2.Start(); | |
| t1.Join(); // чекаємо, поки качка буде готова | |
| t2.Join(); | |
| Console.WriteLine("Качка готова, а пости в соцмережах лайкнуті."); | |
| //////////////////////////////////////////////////////////////////// | |
| Console.WriteLine("Спроба номер 2, але тепер очікування не більше 5 секунд"); | |
| // 2. основний потік чекає результат 5 секунд | |
| duckRoasted = false; | |
| t1 = new(roastDuck); | |
| var roastDuckEvent = new ManualResetEvent(false); | |
| t1.Start(roastDuckEvent); | |
| t2 = new Thread(likeSocialMediaPosts); | |
| t2.Start(); | |
| // чекаємо 5 секунд або завершення задачі із запікання качки | |
| if (roastDuckEvent.WaitOne(5000)) | |
| { | |
| Console.WriteLine("Качка запеклася за 5 секунд! Смачненько!"); | |
| } | |
| else | |
| { | |
| Console.WriteLine("Качка ще не готова, продовжуємо лайкати пости..."); | |
| } | |
| t1.Join(); // чекаємо, поки качка буде готова | |
| t2.Join(); | |
| Console.WriteLine("Смачного!"); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment