Skip to content

Instantly share code, notes, and snippets.

@sunmeat
Last active March 29, 2026 18:45
Show Gist options
  • Select an option

  • Save sunmeat/b8f3cff7c5fcf49cf86e838a88cebebd to your computer and use it in GitHub Desktop.

Select an option

Save sunmeat/b8f3cff7c5fcf49cf86e838a88cebebd to your computer and use it in GitHub Desktop.
WaitOne, volatile
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