Well-Fed Philosophers เบซเบผเบท Competitive .NET Programming

Well-Fed Philosophers เบซเบผเบท Competitive .NET Programming

เปƒเบซเป‰เบžเบงเบเป€เบฎเบปเบฒเป€เบšเบดเปˆเบ‡เบงเบดเบ—เบตเบเบฒเบ™เบ”เปเบฒเป€เบ™เบตเบ™เป‚เบ„เบ‡เบเบฒเบ™เบžเป‰เบญเบกเบเบฑเบ™เปเบฅเบฐเบ‚เบฐเบซเบ™เบฒเบ™เปƒเบ™ .Net, เบเบฒเบ™เบ™เปเบฒเปƒเบŠเป‰เบšเบฑเบ™เบซเบฒเบญเบฒเบซเบฒเบ™เบ‚เบญเบ‡ Philosophers เป€เบ›เบฑเบ™เบ•เบปเบงเบขเปˆเบฒเบ‡. เปเบœเบ™เบเบฒเบ™เปเบกเปˆเบ™เบ™เบตเป‰, เบˆเบฒเบ synchronization เบ‚เบญเบ‡เบเบฐเบ—เบนเป‰ / เบ‚เบฐเบšเบงเบ™เบเบฒเบ™, เบเบฑเบšเบ•เบปเบงเปเบšเบšเบ™เบฑเบเบชเบฐเปเบ”เบ‡ (เปƒเบ™เบžเบฒเบเบชเปˆเบงเบ™เบ”เบฑเปˆเบ‡เบ•เปเปˆเป„เบ›เบ™เบตเป‰). เบšเบปเบ”เบ„เบงเบฒเบกเบญเบฒเบ”เบˆเบฐเป€เบ›เบฑเบ™เบ›เบฐเป‚เบซเบเบ”เบชเปเบฒเบฅเบฑเบšเบ„เบปเบ™เบฎเบนเป‰เบˆเบฑเบเบ—เปเบฒเบญเบดเบ”เบซเบผเบทเป€เบžเบทเปˆเบญเป€เบฎเบฑเบ”เปƒเบซเป‰เบ„เบงเบฒเบกเบฎเบนเป‰เบ‚เบญเบ‡เบ—เปˆเบฒเบ™เบชเบปเบ”เบŠเบทเปˆเบ™.

เป€เบ›เบฑเบ™เบซเบเบฑเบ‡เบกเบฑเบ™เบ—เบฑเบ‡เบซเบกเบปเบ”? Transistors เบšเบฑเบ™เบฅเบธเบ‚เบฐเบซเบ™เบฒเบ”เบ•เปเบฒเปˆเบชเบธเบ”เบ—เบตเปˆเบ‚เบญเบ‡เป€เบ‚เบปเบฒเป€เบˆเบปเป‰เบฒ, เบเบปเบ”เบซเบกเบฒเบ Moore เบžเบฑเบเบœเปˆเบญเบ™เบเปˆเบฝเบงเบเบฑเบšเบเบฒเบ™เบˆเปเบฒเบเบฑเบ”เบ„เบงเบฒเบกเป„เบงเบ‚เบญเบ‡เปเบชเบ‡เบชเบฐเบซเบงเปˆเบฒเบ‡เปเบฅเบฐเบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™เบเบฒเบ™เป€เบžเบตเปˆเบกเบ‚เบถเป‰เบ™เปเบกเปˆเบ™เบชเบฑเบ‡เป€เบเบ”เป€เบซเบฑเบ™เปƒเบ™เบˆเปเบฒเบ™เบงเบ™, transistors เบซเบผเบฒเบเบชเบฒเบกเบฒเบ”เป€เบฎเบฑเบ”เป„เบ”เป‰. เปƒเบ™เป€เบงเบฅเบฒเบ”เบฝเบงเบเบฑเบ™, เบˆเปเบฒเบ™เบงเบ™เบ‚เปเป‰เบกเบนเบ™เบเปเบฒเบฅเบฑเบ‡เป€เบ•เบตเบšเป‚เบ•, เปเบฅเบฐเบœเบนเป‰เปƒเบŠเป‰เบ„เบฒเบ”เบซเบงเบฑเบ‡เบงเปˆเบฒเบเบฒเบ™เบ•เบญเบšเบชเบฐเบซเบ™เบญเบ‡เบ—เบฑเบ™เบ—เบตเบˆเบฒเบเบฅเบฐเบšเบปเบšเบ•เปˆเบฒเบ‡เป†. เปƒเบ™เบชเบฐเบ–เบฒเบ™เบฐเบเบฒเบ™เบ”เบฑเปˆเบ‡เบเปˆเบฒเบง, เบเบฒเบ™เบ‚เบฝเบ™เป‚เบ›เบฅเปเบเบฅเบก "เบ›เบปเบเบเบฐเบ•เบด", เป€เบกเบทเปˆเบญเบžเบงเบเป€เบฎเบปเบฒเบกเบตเบเบฐเบ—เบนเป‰เบ›เบฐเบ•เบดเบšเบฑเบ”เบซเบ™เบถเปˆเบ‡, เบšเปเปˆเบกเบตเบ›เบฐเบชเบดเบ”เบ•เบดเบœเบปเบ™เบญเบตเบเบ•เปเปˆเป„เบ›. เบ—เปˆเบฒเบ™เบˆเปเบฒเป€เบ›เบฑเบ™เบ•เป‰เบญเบ‡เป„เบ”เป‰เปเบเป‰เป„เบ‚ somehow เบšเบฑเบ™เบซเบฒเบ‚เบญเบ‡เบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เบžเป‰เบญเบกเป†เบเบฑเบ™เบซเบผเบท concurrent. เบเบดเปˆเบ‡เป„เบ›เบเบงเปˆเบฒเบ™เบฑเป‰เบ™, เบšเบฑเบ™เบซเบฒเบ™เบตเป‰เบกเบตเบขเบนเปˆเปƒเบ™เบฅเบฐเบ”เบฑเบšเบ•เปˆเบฒเบ‡เป†: เปƒเบ™เบฅเบฐเบ”เบฑเบšเบ‚เบญเบ‡เบเบฐเบ—เบนเป‰, เบฅเบฐเบ”เบฑเบšเบ‚เบฐเบšเบงเบ™เบเบฒเบ™, เปƒเบ™เบฅเบฐเบ”เบฑเบšเป€เบ„เบทเปˆเบญเบ‡เบˆเบฑเบเปƒเบ™เป€เบ„เบทเบญเบ‚เปˆเบฒเบ (เบฅเบฐเบšเบปเบšเบเบฒเบ™เปเบˆเบเบขเบฒเบ). .NET เบกเบตเป€เบ—เบเป‚เบ™เป‚เบฅเบเบตเบ—เบตเปˆเบกเบตเป€เบงเบฅเบฒเบ—เบปเบ”เบชเบญเบšเบ„เบธเบ™เบ™เบฐเบžเบฒเบšเบชเบนเบ‡เป€เบžเบทเปˆเบญเปเบเป‰เป„เบ‚เบšเบฑเบ™เบซเบฒเบ”เบฑเปˆเบ‡เบเปˆเบฒเบงเป„เบ”เป‰เป„เบง เปเบฅเบฐเบกเบตเบ›เบฐเบชเบดเบ”เบ—เบดเบžเบฒเบš.

เบˆเบธเบ”เบ›เบฐเบชเบปเบ‡

Edsger Dijkstra posed เบšเบฑเบ™เบซเบฒเบ™เบตเป‰เบเบฑเบšเบ™เบฑเบเบฎเบฝเบ™เบฅเบฒเบงเปƒเบ™เบ•เบปเป‰เบ™เบ›เบต 1965. เบฎเบนเบšเปเบšเบšเบเบฒเบ™เบชเป‰เบฒเบ‡เบ•เบฑเป‰เบ‡เบ‚เบถเป‰เบ™เปเบกเปˆเบ™เบ”เบฑเปˆเบ‡เบ•เปเปˆเป„เบ›เบ™เบตเป‰. เบกเบตเบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒเบ—เบตเปˆเปเบ™เปˆเบ™เบญเบ™ (เบ›เบปเบเบเบฐเบ•เบดเปเบฅเป‰เบงเบซเป‰เบฒ) เปเบฅเบฐเบ•เบปเบงเป€เบฅเบเบ”เบฝเบงเบเบฑเบ™เบ‚เบญเบ‡เบชเป‰เบญเบก. เป€เบ‚เบปเบฒเป€เบˆเบปเป‰เบฒเบ™เบฑเปˆเบ‡เบขเบนเปˆเป‚เบ•เบฐเบกเบปเบ™, เบกเบตเบชเป‰เบญเบกเบฅเบฐเบซเบงเปˆเบฒเบ‡เป€เบ‚เบปเบฒเป€เบˆเบปเป‰เบฒ. เบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒเบชเบฒเบกเบฒเบ”เบเบดเบ™เบญเบฒเบซเบฒเบ™เบˆเบฒเบเบˆเบฒเบ™เบญเบฒเบซเบฒเบ™เบ—เบตเปˆเบšเปเปˆเบกเบตเบ—เบตเปˆเบชเบดเป‰เบ™เบชเบธเบ”, เบ„เบดเบ”เบซเบผเบทเบฅเปเบ–เป‰เบฒ. เป€เบžเบทเปˆเบญเบเบดเบ™เบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒ, เบ—เปˆเบฒเบ™เบˆเปเบฒเป€เบ›เบฑเบ™เบ•เป‰เบญเบ‡เป€เบญเบปเบฒเบชเบญเบ‡เบชเป‰เบญเบก (เบ„เบปเบ™เบชเบธเบ”เบ—เป‰เบฒเบเปเบšเปˆเบ‡เบ›เบฑเบ™เบชเป‰เบญเบกเบเบฑเบšเบ„เบฑเป‰เบ‡เบ—เปเบฒเบญเบดเบ”). เบเบฒเบ™เบเบปเบเบ‚เบถเป‰เบ™ เปเบฅเบฐเบงเบฒเบ‡เบฅเบปเบ‡เบ—เบฒเบ‡เบชเป‰เบญเบกเปเบกเปˆเบ™เบชเบญเบ‡เบเบฒเบ™เบเบฐเบ—เปเบฒเบ—เบตเปˆเปเบเบเบ•เปˆเบฒเบ‡เบซเบฒเบ. เบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒเบ—เบฑเบ‡เปเบปเบ”เปเบกเปˆเบ™เบกเบดเบ”เบ‡เบฝเบš. เบงเบฝเบเบ‡เบฒเบ™เปเบกเปˆเบ™เป€เบžเบทเปˆเบญเบŠเบญเบเบซเบฒเบชเบนเบ”เบเบฒเบ™เบ„เบดเบ”เป„เบฅเปˆเบ”เบฑเปˆเบ‡เบเปˆเบฒเบงเบ—เบตเปˆเบ—เบฑเบ‡เบซเบกเบปเบ”เบ‚เบญเบ‡เบžเบงเบเป€เบ‚เบปเบฒเบˆเบฐเบ„เบดเบ”เปเบฅเบฐเป€เบ•เบฑเบกเบ—เบตเปˆเป€เบ–เบดเบ‡เปเบกเปˆเบ™เบงเปˆเบฒเบซเบผเบฑเบ‡เบˆเบฒเบ 54 เบ›เบต.

เบ—เปเบฒเบญเบดเบ”, เปƒเบซเป‰เบžเบฐเบเบฒเบเบฒเบกเปเบเป‰เป„เบ‚เบšเบฑเบ™เบซเบฒเบ™เบตเป‰เป‚เบ”เบเบœเปˆเบฒเบ™เบเบฒเบ™เบ™เปเบฒเปƒเบŠเป‰เบžเบทเป‰เบ™เบ—เบตเปˆเบฎเปˆเบงเบกเบเบฑเบ™. เบชเป‰เบญเบกเบ™เบญเบ™เบขเบนเปˆเป€เบ—เบดเบ‡เป‚เบ•เบฐเบ—เบปเปˆเบงเป„เบ› เปเบฅเบฐเบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒเบžเบฝเบ‡เปเบ•เปˆเป€เบญเบปเบฒเบžเบงเบเบกเบฑเบ™เป€เบกเบทเปˆเบญเบžเบงเบเป€เบ‚เบปเบฒเบขเบนเปˆเปเบฅเป‰เบงเป€เบญเบปเบฒเบ„เบทเบ™. เบ—เบตเปˆเบ™เบตเป‰เบกเบตเบšเบฑเบ™เบซเบฒเบเบฑเบš synchronization, เปƒเบ™เป€เบงเบฅเบฒเบ—เบตเปˆเปเบ™เปˆเบ™เบญเบ™เบ—เบตเปˆเบˆเบฐเป€เบญเบปเบฒ surebets? เบˆเบฐเป€เบ›เบฑเบ™เปเบ™เบงเปƒเบ”เบ–เป‰เบฒเบšเปเปˆเบกเบตเบชเป‰เบญเบก? เปเบฅเบฐเบญเบทเปˆเบ™เป† เปเบ•เปˆเบ—เปเบฒเบญเบดเบ”, เปƒเบซเป‰เป€เบฅเบตเปˆเบกเบ•เบปเป‰เบ™เบ‚เบญเบ‡ philosophers เป„เบ”เป‰.

เป€เบžเบทเปˆเบญเป€เบฅเบตเปˆเบกเบ•เบปเป‰เบ™ threads, เบžเบงเบเป€เบฎเบปเบฒเปƒเบŠเป‰ thread pool เบœเปˆเบฒเบ™ Task.Run เบงเบดเบ—เบตเบเบฒเบ™:

var cancelTokenSource = new CancellationTokenSource();
Action<int> create = (i) => RunPhilosopher(i, cancelTokenSource.Token);
for (int i = 0; i < philosophersAmount; i++) 
{
    int icopy = i;
    // ะŸะพะผะตัั‚ะธั‚ัŒ ะทะฐะดะฐั‡ัƒ ะฒ ะพั‡ะตั€ะตะดัŒ ะฟัƒะปะฐ ะฟะพั‚ะพะบะพะฒ. ะœะตั‚ะพะด RunDeadlock ะฝะต ะทะฐะฟัƒัะบะฐะตั‚ัŒัั 
    // ัั€ะฐะทัƒ, ะฐ ะถะดะตั‚ ัะฒะพะตะณะพ ะฟะพั‚ะพะบะฐ. ะัะธะฝั…ั€ะพะฝะฝั‹ะน ะทะฐะฟัƒัะบ.
    philosophers[i] = Task.Run(() => create(icopy), cancelTokenSource.Token);
}

เบชเบฐเบ™เบธเบเป€เบเบตเบเบฐเบ—เบนเป‰เบ–เบทเบเบญเบญเบเปเบšเบšเบกเบฒเป€เบžเบทเปˆเบญเป€เบžเบตเปˆเบกเบ›เบฐเบชเบดเบ”เบ—เบดเบžเบฒเบšเบเบฒเบ™เบชเป‰เบฒเบ‡เปเบฅเบฐเบฅเบถเบš thread. เบชเบฐเบฅเบญเบเบ™เป‰เบณเบ™เบตเป‰เบกเบตเปเบ–เบงเบ—เบตเปˆเบกเบตเปœเป‰เบฒเบงเบฝเบ เปเบฅเบฐ CLR เบชเป‰เบฒเบ‡ เบซเบผเบทเบฅเบถเบšเบเบฐเบ—เบนเป‰เบ‚เบถเป‰เบ™เบเบฑเบšเบˆเบณเบ™เบงเบ™เบ‚เบญเบ‡เปœเป‰เบฒเบงเบฝเบเป€เบซเบผเบปเปˆเบฒเบ™เบตเป‰. เบชเบฐเบ™เบธเบเป€เบเบตเบ”เบฝเบงเบชเปเบฒเบฅเบฑเบš AppDomains เบ—เบฑเบ‡เบซเบกเบปเบ”. เบชเบฐเบ™เบธเบเป€เบเบตเบ™เบตเป‰เบ„เบงเบ™เบˆเบฐเบ–เบทเบเบ™เปเบฒเปƒเบŠเป‰เป€เบเบทเบญเบšเบชเบฐเป€เบซเบกเบต, เป€เบžเบฒเบฐเบงเปˆเบฒ. เบšเปเปˆเบˆเปเบฒเป€เบ›เบฑเบ™เบ•เป‰เบญเบ‡เบฅเบปเบšเบเบงเบ™เบเบฒเบ™เบชเป‰เบฒเบ‡, เบฅเบถเบšเบเบฐเบ—เบนเป‰, เปเบ–เบงเบ‚เบญเบ‡เป€เบ‚เบปเบฒเป€เบˆเบปเป‰เบฒ, เปเบฅเบฐเบญเบทเปˆเบ™เป†. เบกเบฑเบ™เป€เบ›เบฑเบ™เป„เบ›เป„เบ”เป‰เป‚เบ”เบเบšเปเปˆเบกเบตเบเบฒเบ™เบชเบฐเบ™เบธเบเป€เบเบต, เปเบ•เปˆเบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™เบ—เปˆเบฒเบ™เบ•เป‰เบญเบ‡เปƒเบŠเป‰เบกเบฑเบ™เป‚เบ”เบเบเบปเบ‡. Thread, เบ™เบตเป‰เปเบกเปˆเบ™เป€เบ›เบฑเบ™เบ›เบฐเป‚เบซเบเบ”เบชเปเบฒเบฅเบฑเบšเบเปเบฅเบฐเบ™เบตเบ—เบตเปˆเบ—เปˆเบฒเบ™เบˆเปเบฒเป€เบ›เบฑเบ™เบ•เป‰เบญเบ‡เบกเบตเบเบฒเบ™เบ›เปˆเบฝเบ™เปเบ›เบ‡เบšเบนเบฅเบดเบกเบฐเบชเบดเบ”เบ‚เบญเบ‡ thread, เปƒเบ™เป€เบงเบฅเบฒเบ—เบตเปˆเบžเบงเบเป€เบฎเบปเบฒเบกเบตเบเบฒเบ™เบ”เปเบฒเป€เบ™เบตเบ™เบ‡เบฒเบ™เบเบฒเบง, เบชเปเบฒเบฅเบฑเบšเบซเบปเบงเบ‚เปเป‰ Foreground, เปเบฅเบฐเบญเบทเปˆเบ™เป†.

เปƒเบ™เบ„เปเบฒเบชเบฑเบšเบ•เปˆเบฒเบ‡เป†เบญเบทเปˆเบ™เป†, System.Threading.Tasks.Task เบซเป‰เบญเบ‡เบฎเบฝเบ™เปเบกเปˆเบ™เบ„เบทเบเบฑเบ™ Thread, เปเบ•เปˆเบกเบตเบ—เบธเบเบ›เบฐเป€เบžเบ”เบ‚เบญเบ‡เบ„เบงเบฒเบกเบชเบฐเบ”เบงเบ: เบ„เบงเบฒเบกเบชเบฒเบกเบฒเบ”เปƒเบ™เบเบฒเบ™เบ”เปเบฒเป€เบ™เบตเบ™เบเบฒเบ™เบงเบฝเบเบ‡เบฒเบ™เบซเบผเบฑเบ‡เบˆเบฒเบเบ•เบฑเบ™เบ‚เบญเบ‡เบงเบฝเบเบ‡เบฒเบ™เบญเบทเปˆเบ™เป†, เบเบฑเบšเบ„เบทเบ™เปƒเบซเป‰เป€เบ‚เบปเบฒเป€เบˆเบปเป‰เบฒเบˆเบฒเบเบซเบ™เป‰เบฒเบ—เบตเปˆ, เบชเบฐเบ”เบงเบเบ‚เบฑเบ”เบ‚เบงเบฒเบ‡เบžเบงเบเป€เบ‚เบปเบฒ, เปเบฅเบฐเบญเบทเปˆเบ™เป†. เปเบฅเบฐเบญเบทเปˆเบ™เป†.เบžเบงเบเป€เบ‚เบปเบฒเบกเบตเบ„เบงเบฒเบกเบˆเปเบฒเป€เบ›เบฑเบ™เป€เบžเบทเปˆเบญเบชเบฐเบซเบ™เบฑเบšเบชเบฐเบซเบ™เบนเบ™ async / เบฅเปเบ–เป‰เบฒเบเบฒเบ™เบเปเปˆเบชเป‰เบฒเบ‡ (Task-based Asynchronous Pattern, เป‰เปเบฒเบ•เบฒเบ™ syntactic เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบฅเปเบ–เป‰เบฒเบเบฒเบ™เบ”เปเบฒเป€เบ™เบตเบ™เบ‡เบฒเบ™ IO). เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเป€เบงเบปเป‰เบฒเบเปˆเบฝเบงเบเบฑเบšเป€เบฅเบทเปˆเบญเบ‡เบ™เบตเป‰เบ•เปเปˆเบกเบฒ.

CancelationTokenSource เปƒเบ™เบ—เบตเปˆเบ™เบตเป‰เบกเบฑเบ™เป€เบ›เบฑเบ™เบชเบดเปˆเบ‡เบˆเปเบฒเป€เบ›เบฑเบ™เป€เบžเบทเปˆเบญเปƒเบซเป‰เบเบฐเบ—เบนเป‰เบชเบฒเบกเบฒเบ”เบขเบธเบ”เบ•เบปเบงเบ‚เบญเบ‡เบกเบฑเบ™เป€เบญเบ‡เบขเบนเปˆเบ—เบตเปˆเบชเบฑเบ™เบเบฒเบ™เบ‚เบญเบ‡เบเบฐเบ—เบนเป‰เบเบฒเบ™เป‚เบ—.

เบšเบฑเบ™เบซเบฒเบเบฒเบ™เบŠเบดเบ‡เบ„เปŒ

เบ•เบฑเบ™เบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒ

เบ•เบปเบเบฅเบปเบ‡, เบžเบงเบเป€เบฎเบปเบฒเบฎเบนเป‰เบงเบดเบ—เบตเบชเป‰เบฒเบ‡เบเบฐเบ—เบนเป‰, เปƒเบซเป‰เบฅเบญเบ‡เบเบดเบ™เป€เบ‚เบปเป‰เบฒเบ—เปˆเบฝเบ‡:

// ะšั‚ะพ ะบะฐะบะธะต ะฒะธะปะบะธ ะฒะทัะป. ะš ะฟั€ะธะผะตั€ัƒ: 1 1 3 3 - 1ะน ะธ 3ะน ะฒะทัะปะธ ะฟะตั€ะฒั‹ะต ะดะฒะต ะฟะฐั€ั‹.
private int[] forks = Enumerable.Repeat(0, philosophersAmount).ToArray();

// ะขะพ ะถะต, ั‡ั‚ะพ RunPhilosopher()
private void RunDeadlock(int i, CancellationToken token) 
{
    // ะ–ะดะฐั‚ัŒ ะฒะธะปะบัƒ, ะฒะทัั‚ัŒ ะตั‘. ะญะบะฒะธะฒะฐะปะตะฝั‚ะฝะพ: 
    // while(true) 
    //     if forks[fork] == 0 
    //          forks[fork] = i+1
    //          break
    //     Thread.Sleep() ะธะปะธ Yield() ะธะปะธ SpinWait()
    void TakeFork(int fork) =>
        SpinWait.SpinUntil(() => 
            Interlocked.CompareExchange(ref forks[fork], i+1, 0) == 0);

    // ะ”ะปั ะฟั€ะพัั‚ะพั‚ั‹, ะฝะพ ะผะพะถะฝะพ ั Interlocked.Exchange:
    void PutFork(int fork) => forks[fork] = 0;

    while (true)
    {
        TakeFork(Left(i));
        TakeFork(Right(i));
        eatenFood[i] = (eatenFood[i] + 1) % (int.MaxValue - 1);
        PutFork(Left(i));
        PutFork(Right(i));
        Think(i);

        // ะ—ะฐะฒะตั€ัˆะธั‚ัŒ ั€ะฐะฑะพั‚ัƒ ะฟะพ-ั…ะพั€ะพัˆะตะผัƒ.
        token.ThrowIfCancellationRequested();
    }
}

เปƒเบ™เบ—เบตเปˆเบ™เบตเป‰เบžเบงเบเป€เบฎเบปเบฒเบ—เปเบฒเบญเบดเบ”เบžเบฐเบเบฒเบเบฒเบกเป€เบญเบปเบฒเบชเป‰เบญเบกเบŠเป‰เบฒเบ, เปเบฅเบฐเบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™เบชเป‰เบญเบกเบ‚เบงเบฒ, เปเบฅเบฐเบ–เป‰เบฒเบซเบฒเบเบงเปˆเบฒเบกเบฑเบ™เป€เบฎเบฑเบ”เบงเบฝเบเบญเบญเบ, เบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™เบžเบงเบเป€เบฎเบปเบฒเบเบดเบ™เบญเบฒเบซเบฒเบ™เปเบฅเบฐเปƒเบซเป‰เป€เบ‚เบปเบฒเป€เบˆเบปเป‰เบฒเบเบฑเบšเบ„เบทเบ™เป„เบ›เบšเปˆเบญเบ™. เป€เบญเบปเบฒเบซเบ™เบถเปˆเบ‡เบชเป‰เบญเบกเปเบกเปˆเบ™เบ›เบฐเบฅเปเบฒเบกเบฐเบ™เบน, i.e. เบชเบญเบ‡เบเบฐเบ—เบนเป‰เบšเปเปˆเบชเบฒเบกเบฒเบ”เป€เบญเบปเบฒเบซเบ™เบถเปˆเบ‡เปƒเบ™เป€เบงเบฅเบฒเบ”เบฝเบงเบเบฑเบ™ (เบšเปเปˆเบ–เบทเบเบ•เป‰เบญเบ‡: เบ—เปเบฒเบญเบดเบ”เบญเปˆเบฒเบ™เบงเปˆเบฒเบชเป‰เบญเบกเปเบกเปˆเบ™เบšเปเปˆเป€เบชเบเบ„เปˆเบฒ, เบ—เบตเบชเบญเบ‡ - เป€เบŠเบฑเปˆเบ™เบ”เบฝเบงเบเบฑเบ™, เบ—เปเบฒเบญเบดเบ”เปƒเบŠเป‰เป€เบงเบฅเบฒ, เบ—เบตเบชเบญเบ‡เปƒเบŠเป‰เป€เบงเบฅเบฒ). เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ™เบตเป‰ Interlocked.CompareExchange, เป€เบŠเบดเปˆเบ‡เบ•เป‰เบญเบ‡เป„เบ”เป‰เบฎเบฑเบšเบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เบ”เป‰เบงเบเบ„เปเบฒเปเบ™เบฐเบ™เปเบฒเบ‚เบญเบ‡เป‚เบ›เป€เบŠเบ”เป€เบŠเบต (TSL, XCHG), เป€เบŠเบดเปˆเบ‡ locks เบŠเบดเป‰เบ™เบชเปˆเบงเบ™เบ‚เบญเบ‡เบ„เบงเบฒเบกเบŠเบปเบ‡เบˆเปเบฒเบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบญเปˆเบฒเบ™เบฅเปเบฒเบ”เบฑเบšเบ›เบฐเบฅเปเบฒเบกเบฐเบ™เบนเปเบฅเบฐเบเบฒเบ™เบ‚เบฝเบ™. เปเบฅเบฐ SpinWait เปเบกเปˆเบ™เบ—เบฝเบšเป€เบ—เบปเปˆเบฒเบเบฑเบšเบเบฒเบ™เบเปเปˆเบชเป‰เบฒเบ‡ while(true) เบžเบฝเบ‡เปเบ•เปˆเบกเบต "magic" เป€เบฅเบฑเบเบ™เป‰เบญเบ - เบเบฐเบ—เบนเป‰เปƒเบŠเป‰เป€เบงเบฅเบฒเป‚เบฎเบ‡เบ‡เบฒเบ™เบœเบฐเบฅเบดเบ” (Thread.SpinWait), เปเบ•เปˆโ€‹เบšเบฒเบ‡โ€‹เบ„เบฑเป‰เบ‡โ€‹เบเบฒเบ™โ€‹เป‚เบญเบ™โ€‹เบเบฒเบ™โ€‹เบ„เบงเบšโ€‹เบ„เบธเบกโ€‹เบเบฑเบšโ€‹เบเบฐโ€‹เบ—เบนเป‰โ€‹เบญเบทเปˆเบ™ (Thread.Yeild) เบซเบผเบทโ€‹เบ™เบญเบ™โ€‹เบซเบฅเบฑเบš (Thread.Sleep).

เปเบ•เปˆเบเบฒเบ™เปเบเป‰เป„เบ‚เบ™เบตเป‰เบšเปเปˆเป„เบ”เป‰เบœเบปเบ™, เป€เบžเบฒเบฐเบงเปˆเบฒ เบเบฒเบ™เป„เบซเบผเป€เบ‚เบปเป‰เบฒเปƒเบ™เป„เบงเป†เบ™เบตเป‰ (เบชเปเบฒเบฅเบฑเบšเบ‚เป‰เบญเบเบžเบฒเบเปƒเบ™เบซเบ™เบถเปˆเบ‡เบงเบดเบ™เบฒเบ—เบต) เป„เบ”เป‰เบ–เบทเบเบชเบฐเบเบฑเบ”: เบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒเบ—เบฑเบ‡เบซเบกเบปเบ”เปƒเบŠเป‰เบชเป‰เบญเบกเบŠเป‰เบฒเบเบ‚เบญเบ‡เป€เบ‚เบปเบฒเป€เบˆเบปเป‰เบฒ, เปเบ•เปˆเบšเปเปˆเปเบกเปˆเบ™เบ—เบตเปˆเบ–เบทเบเบ•เป‰เบญเบ‡. array เบ‚เบญเบ‡เบชเป‰เบญเบกเบกเบตเบ„เปˆเบฒ: 1 2 3 4 5.

Well-Fed Philosophers เบซเบผเบท Competitive .NET Programming

เปƒเบ™เบฎเบนเบš, เบšเบฅเบฑเบญเบเบเบฐเบ—เบนเป‰ (deadlock). เบชเบตเบ‚เบฝเบง - เบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”, เบชเบตเปเบ”เบ‡ - synchronization, เบชเบตเบ‚เบตเป‰เป€เบ–เบปเปˆเบฒ - เบเบฐเบ—เบนเป‰เปเบกเปˆเบ™เบ™เบญเบ™. rhombuses เบŠเบตเป‰เบšเบญเบเป€เบงเบฅเบฒเป€เบฅเบตเปˆเบกเบ•เบปเป‰เบ™เบ‚เบญเบ‡ Tasks.

เบ„เบงเบฒเบกเบญเบถเบ”เบซเบดเบงเบ‚เบญเบ‡เบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒ

เป€เบ–เบดเบ‡เปเบกเปˆเบ™เบงเปˆเบฒเบกเบฑเบ™เบšเปเปˆเบˆเปเบฒเป€เบ›เบฑเบ™เบ—เบตเปˆเบˆเบฐเบ„เบดเบ”เบซเบผเบฒเบเป‚เบ”เบเบชเบฐเป€เบžเบฒเบฐเบญเบฒเบซเบฒเบ™, เปเบ•เปˆเบ„เบงเบฒเบกเบญเบถเบ”เบซเบดเบงเป€เบฎเบฑเบ”เปƒเบซเป‰เบœเบนเป‰เปƒเบ”เบ›เบฐเบ–เบดเป‰เบกเบ›เบฑเบ”เบŠเบฐเบเบฒ. เปƒเบซเป‰เบžเบฐเบเบฒเบเบฒเบกเบˆเปเบฒเบฅเบญเบ‡เบชเบฐเบ–เบฒเบ™เบฐเบเบฒเบ™เบ‚เบญเบ‡เบ„เบงเบฒเบกเบญเบถเบ”เบซเบดเบงเบ‚เบญเบ‡เบเบฐเบ—เบนเป‰เปƒเบ™เบšเบฑเบ™เบซเบฒเบ‚เบญเบ‡เบžเบงเบเป€เบฎเบปเบฒ. เบ„เบงเบฒเบกเบญเบถเบ”เบซเบดเบงเปเบกเปˆเบ™เปƒเบ™เป€เบงเบฅเบฒเบ—เบตเปˆเบเบฐเบ—เบนเป‰เบเปเบฒเบฅเบฑเบ‡เปเบฅเปˆเบ™, เปเบ•เปˆเบšเปเปˆเบกเบตเบงเบฝเบเบ—เบตเปˆเบชเปเบฒเบ„เบฑเบ™, เป€เบงเบปเป‰เบฒเบญเบตเบเบขเปˆเบฒเบ‡เบซเบ™เบถเปˆเบ‡, เบ™เบตเป‰เปเบกเปˆเบ™เบ„เบงเบฒเบกเบ•เบฒเบเบ„เบทเบเบฑเบ™, เบžเบฝเบ‡เปเบ•เปˆเบ›เบฐเบˆเบธเบšเบฑเบ™เบเบฐเบ—เบนเป‰เบšเปเปˆเป„เบ”เป‰เบ™เบญเบ™, เปเบ•เปˆเบขเปˆเบฒเบ‡เบซเป‰เบฒเบงเบซเบฑเบ™เบŠเบญเบเบซเบฒเบšเบฒเบ‡เบชเบดเปˆเบ‡เบšเบฒเบ‡เบขเปˆเบฒเบ‡เบเบดเบ™, เปเบ•เปˆเบšเปเปˆเบกเบตเบญเบฒเบซเบฒเบ™. เป€เบžเบทเปˆเบญเบซเบผเบตเบเป€เบงเบฑเป‰เบ™เบเบฒเบ™เบ‚เบฑเบ”เบ‚เบงเบฒเบ‡เป€เบฅเบทเป‰เบญเบเป†, เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเป€เบญเบปเบฒเบชเป‰เบญเบกเบ„เบทเบ™เบ–เป‰เบฒเบžเบงเบเป€เบฎเบปเบฒเบšเปเปˆเบชเบฒเบกเบฒเบ”เป€เบญเบปเบฒเบญเบฑเบ™เบญเบทเปˆเบ™เป„เบ”เป‰.

// ะขะพ ะถะต ั‡ั‚ะพ ะธ ะฒ RunDeadlock, ะฝะพ ั‚ะตะฟะตั€ัŒ ะบะปะฐะดะตะผ ะฒะธะปะบัƒ ะฝะฐะทะฐะด ะธ ะดะพะฑะฐะฒะปัะตะผ ะฟะปะพั…ะธั… ั„ะธะปะพัะพั„ะพะฒ.
private void RunStarvation(int i, CancellationToken token)
{
    while (true)
    {
        bool hasTwoForks = false;
        var waitTime = TimeSpan.FromMilliseconds(50);
        // ะŸะปะพั…ะพะน ั„ะธะปะพัะพั„ะพะฒ ะผะพะถะตั‚ ัƒะถะต ะธะผะตั‚ัŒ ะฒะธะปะบัƒ:
        bool hasLeft = forks[Left(i)] == i + 1;
        if (hasLeft || TakeFork(Left(i), i + 1, waitTime))
        {
            if (TakeFork(Right(i), i + 1, TimeSpan.Zero))
                hasTwoForks = true;
            else
                PutFork(Left(i)); // ะ˜ะฝะพะณะดะฐ ะฟะปะพั…ะพะน ั„ะธะปะพัะพั„ ะพั‚ะดะฐะตั‚ ะฒะธะปะบัƒ ะฝะฐะทะฐะด.
        } 
        if (!hasTwoForks)
        {
            if (token.IsCancellationRequested) break;
            continue;
        }
        eatenFood[i] = (eatenFood[i] + 1) % (int.MaxValue - 1);
        bool goodPhilosopher = i % 2 == 0;
        // ะ ะฟะปะพั…ะพะน ั„ะธะปะพัะพั„ ะทะฐะฑั‹ะฒะฐะตั‚ ะฟะพะปะพะถะธั‚ัŒ ัะฒะพัŽ ะฒะธะปะบัƒ ะพะฑั€ะฐั‚ะฝะพ:
        if (goodPhilosopher)
            PutFork(Left(i));
        // ะ ะตัะปะธ ะธ ะฟั€ะฐะฒัƒัŽ ะฝะต ะฟะพะปะพะถะธั‚, ั‚ะพ ั…ะพั€ะพัˆะธะต ะฑัƒะดัƒั‚ ะฒะพะพะฑั‰ะต ะฑะตะท ะตะดั‹.
        PutFork(Right(i));

        Think(i);

        if (token.IsCancellationRequested)
            break;
    }
}

// ะขะตะฟะตั€ัŒ ะผะพะถะฝะพ ะถะดะฐั‚ัŒ ะพะฟั€ะตะดะตะปะตะฝะฝะพะต ะฒั€ะตะผั.
bool TakeFork(int fork, int philosopher, TimeSpan? waitTime = null)
{
    return SpinWait.SpinUntil(
        () => Interlocked.CompareExchange(ref forks[fork], philosopher, 0) == 0,
              waitTime ?? TimeSpan.FromMilliseconds(-1)
    );
}

เบชเบดเปˆเบ‡เบ—เบตเปˆเบชเปเบฒเบ„เบฑเบ™เบเปˆเบฝเบงเบเบฑเบšเบฅเบฐเบซเบฑเบ”เบ™เบตเป‰เปเบกเปˆเบ™เบงเปˆเบฒเบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒเบชเบญเบ‡เบ„เบปเบ™เปƒเบ™เบชเบตเปˆเบ„เบปเบ™เบฅเบทเบกเป€เบญเบปเบฒเบ—เบฒเบ‡เปเบเบเบŠเป‰เบฒเบเบ‚เบญเบ‡เบžเบงเบเป€เบ‚เบปเบฒเบฅเบปเบ‡. เปเบฅเบฐเบกเบฑเบ™ turns เปƒเบซเป‰เป€เบซเบฑเบ™เบงเปˆเบฒเบžเบงเบเป€เบ‚เบปเบฒเบเบดเบ™เบญเบฒเบซเบฒเบ™เบซเบผเบฒเบ, เปƒเบ™เบ‚เบฐเบ™เบฐเบ—เบตเปˆเบ„เบปเบ™เบญเบทเปˆเบ™เป€เบฅเบตเปˆเบกเบซเบดเบง, เป€เบ–เบดเบ‡เปเบกเปˆเบ™เบงเปˆเบฒเบเบฐเบ—เบนเป‰เบกเบตเบšเบนเบฅเบดเบกเบฐเบชเบดเบ”เบ”เบฝเบงเบเบฑเบ™. เปƒเบ™เบ—เบตเปˆเบ™เบตเป‰เบžเบงเบเป€เบ‚เบปเบฒเบšเปเปˆเป„เบ”เป‰เบญเบถเบ”เบซเบดเบงเบขเปˆเบฒเบ‡เบชเบปเบกเบšเบนเบ™, เป€เบžเบฒเบฐเบงเปˆเบฒ. เบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒเบ—เบตเปˆเบšเปเปˆเบ”เบตเป€เบฎเบฑเบ”เปƒเบซเป‰เบชเป‰เบญเบกเบ‚เบญเบ‡เป€เบ‚เบปเบฒเป€เบˆเบปเป‰เบฒเบ„เบทเบ™เบšเบฒเบ‡เบ„เบฑเป‰เบ‡. เบ›เบฐเบเบปเบ”เบงเปˆเบฒเบ„เบปเบ™เบ”เบตเบเบดเบ™เปœเป‰เบญเบเบเบงเปˆเบฒเบ„เบปเบ™เบšเปเปˆเบ”เบตเบ›เบฐเบกเบฒเบ™ 5 เป€เบ—เบปเปˆเบฒ. เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™เบ„เบงเบฒเบกเบœเบดเบ”เบžเบฒเบ”เบ‚เบฐเบซเบ™เบฒเบ”เบ™เป‰เบญเบเปƒเบ™เบฅเบฐเบซเบฑเบ”เบ™เปเบฒเป„เบ›เบชเบนเปˆเบเบฒเบ™เบซเบผเบธเบ”เบฅเบปเบ‡เปƒเบ™เบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”. เบกเบฑเบ™เบเบฑเบ‡เป€เบ›เบฑเบ™เบกเบนเบ™เบ„เปˆเบฒเบ—เบตเปˆเบชเบฑเบ‡เป€เบเบ”เบงเปˆเบฒเบชเบฐเบ–เบฒเบ™เบฐเบเบฒเบ™เบ—เบตเปˆเบซเบฒเบเบฒเบเปเบกเปˆเบ™เป€เบ›เบฑเบ™เป„เบ›เป„เบ”เป‰เป€เบกเบทเปˆเบญเบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒเบ—เบฑเบ‡เบซเบกเบปเบ”เปƒเบŠเป‰เบชเป‰เบญเบกเบŠเป‰เบฒเบ, เบšเปเปˆเบกเบตเบ‚เบงเบฒ, เบžเบงเบเป€เบ‚เบปเบฒเป€เบญเบปเบฒเบŠเป‰เบฒเบ, เบฅเปเบ–เป‰เบฒ, เป€เบญเบปเบฒเบŠเป‰เบฒเบเบญเบตเบเป€เบ—เบทเปˆเบญเบซเบ™เบถเปˆเบ‡, เปเบฅเบฐเบญเบทเปˆเบ™เป†. เบชเบฐเบ–เบฒเบ™เบฐเบเบฒเบ™เบ™เบตเป‰เบเบฑเบ‡เป€เบ›เบฑเบ™เบ„เบงเบฒเบกเบญเบถเบ”เบซเบดเบง, เบ„เบทเบเบฑเบšเบ„เบงเบฒเบกเบ•เบฒเบ. เบ‚เป‰เบญเบเบฅเบปเป‰เบกเป€เบซเบฅเบงเปƒเบ™เบเบฒเบ™เป€เบฎเบฑเบ”เบŠเป‰เปเบฒเบกเบฑเบ™. เบ‚เป‰เบฒเบ‡เบฅเบธเปˆเบกเบ™เบตเป‰เปเบกเปˆเบ™เบฎเบนเบšเบชเปเบฒเบฅเบฑเบšเบชเบฐเบ–เบฒเบ™เบฐเบเบฒเบ™เบ—เบตเปˆเบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒเบ—เบตเปˆเบšเปเปˆเบ”เบตเบชเบญเบ‡เบ„เบปเบ™เป„เบ”เป‰เป€เบญเบปเบฒเบ—เบฑเบ‡เบชเบญเบ‡เบชเป‰เบญเบกเปเบฅเบฐเบชเบญเบ‡เบ„เบปเบ™เบ”เบตเบเปเบฒเบฅเบฑเบ‡เบซเบดเบงเป‚เบซเบ.

Well-Fed Philosophers เบซเบผเบท Competitive .NET Programming

เปƒเบ™เบ—เบตเปˆเบ™เบตเป‰เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เป€เบซเบฑเบ™เป„เบ”เป‰เบงเปˆเบฒเบเบฐเบ—เบนเป‰เบ•เบทเปˆเบ™เบ‚เบถเป‰เบ™เบšเบฒเบ‡เบ„เบฑเป‰เบ‡เปเบฅเบฐเบžเบฐเบเบฒเบเบฒเบกเป€เบญเบปเบฒเบŠเบฑเบšเบžเบฐเบเบฒเบเบญเบ™. เบชเบญเบ‡เบ‚เบญเบ‡เบชเบตเปˆเปเบเบ™เบšเปเปˆเป€เบฎเบฑเบ”เบซเบเบฑเบ‡เป€เบฅเบตเบ (เป€เบชเบฑเป‰เบ™เบชเบฐเปเบ”เบ‡เบชเบตเบ‚เบฝเบงเบ‚เป‰เบฒเบ‡เป€เบ—เบดเบ‡).

เบเบฒเบ™เป€เบชเบเบŠเบตเบงเบดเบ”เบ‚เบญเบ‡เบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒ

เปเบฅเป‰เบง, เบšเบฑเบ™เบซเบฒเบญเบตเบเบขเปˆเบฒเบ‡เบซเบ™เบถเปˆเบ‡เบ—เบตเปˆเบชเบฒเบกเบฒเบ”เบ‚เบฑเบ”เบ‚เบงเบฒเบ‡เบเบฒเบ™เบเบดเบ™เป€เบ‚เบปเป‰เบฒเปเบฅเบ‡เบญเบฑเบ™เบฎเบธเปˆเบ‡เป‚เบฅเบ”เบ‚เบญเบ‡เบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒเปเบกเปˆเบ™เบ–เป‰เบฒเบซเบ™เบถเปˆเบ‡เปƒเบ™เบžเบงเบเบกเบฑเบ™เบ•เบฒเบเบ—เบฑเบ™เบ—เบตเบ—เบฑเบ™เปƒเบ”เบ”เป‰เบงเบเบชเป‰เบญเบกเบขเบนเปˆเปƒเบ™เบกเบทเบ‚เบญเบ‡เบฅเบฒเบง (เปเบฅเบฐเบžเบงเบเป€เบ‚เบปเบฒเบˆเบฐเบเบฑเบ‡เบฅเบฒเบงเปเบšเบšเบ™เบฑเป‰เบ™). เบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™, เบ›เบฐเป€เบ—เบ”เป€เบžเบทเปˆเบญเบ™เบšเป‰เบฒเบ™เบˆเบฐเบ–เบทเบเบ›เบฐเป„เบงเป‰เป‚เบ”เบเบšเปเปˆเบกเบตเบญเบฒเบซเบฒเบ™เบ„เปˆเปเบฒ. เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เบกเบฒเบžเป‰เบญเบกเบเบฑเบšเบฅเบฐเบซเบฑเบ”เบ•เบปเบงเบขเปˆเบฒเบ‡เบชเปเบฒเบฅเบฑเบšเบเปเบฅเบฐเบ™เบตเบ™เบตเป‰เบ•เบปเบงเบ—เปˆเบฒเบ™เป€เบญเบ‡, เบ•เบปเบงเบขเปˆเบฒเบ‡, เบกเบฑเบ™เบ–เบทเบเบ–เบดเป‰เบกเบญเบญเบ NullReferenceException เบซเบผเบฑเบ‡เบˆเบฒเบ philosopher เปƒเบŠเป‰เป€เบงเบฅเบฒเบชเป‰เบญเบก. เปเบฅเบฐ, เป‚เบ”เบเบงเบดเบ—เบตเบ—เบฒเบ‡เบเบฒเบ™, เบ‚เปเป‰เบเบปเบเป€เบงเบฑเป‰เบ™เบˆเบฐเบšเปเปˆเบ–เบทเบเบˆเบฑเบ”เบเบฒเบ™เปเบฅเบฐเบฅเบฐเบซเบฑเบ”เบเบฒเบ™เป‚เบ—เบˆเบฐเบšเปเปˆเบžเบฝเบ‡เปเบ•เปˆเบˆเบฑเบšเบกเบฑเบ™ (เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ™เบตเป‰ AppDomain.CurrentDomain.UnhandledException เปเบฅเบฐ เบญเบทเปˆเบ™เป†). เป€เบžเบฒเบฐเบชเบฐเบ™เบฑเป‰เบ™, เบเบฒเบ™เบˆเบฑเบ”เบเบฒเบ™เบ„เบงเบฒเบกเบœเบดเบ”เบžเบฒเบ”เปเบกเปˆเบ™เบˆเปเบฒเป€เบ›เบฑเบ™เปƒเบ™เบเบฐเบ—เบนเป‰เบ•เบปเบงเป€เบญเบ‡เปเบฅเบฐเบ”เป‰เบงเบเบเบฒเบ™เบขเบธเบ”เป€เบŠเบปเบฒเบขเปˆเบฒเบ‡เบชเบฐเบซเบ‡เปˆเบฒเบ‡เบฒเบก.

The waiter

เบ•เบปเบเบฅเบปเบ‡, เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเปเบเป‰เป„เบ‚เบšเบฑเบ™เบซเบฒเบเบฒเบ™เบขเบธเบ”เบŠเบฐเบ‡เบฑเบ, เบ„เบงเบฒเบกเบญเบถเบ”เบซเบดเบง, เปเบฅเบฐเบ„เบงเบฒเบกเบ•เบฒเบเบ™เบตเป‰เปเบ™เบงเปƒเบ”? เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเบญเบฐเบ™เบธเบเบฒเบ”เปƒเบซเป‰เบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒเบžเบฝเบ‡เบ„เบปเบ™เบ”เบฝเบงเป€เบ‚เบปเป‰เบฒเบซเบฒเบ—เบฒเบ‡เบชเป‰เบญเบก, เป€เบžเบตเปˆเบกเบเบฒเบ™เบเบปเบเป€เบงเบฑเป‰เบ™เป€เบŠเบดเปˆเบ‡เบเบฑเบ™เปเบฅเบฐเบเบฑเบ™เบ‚เบญเบ‡เบเบฐเบ—เบนเป‰เบชเปเบฒเบฅเบฑเบšเบชเบฐเบ–เบฒเบ™เบ—เบตเปˆเบ™เบตเป‰. เป€เบฎเบฑเบ”เปเบ™เบงเปƒเบ”เบกเบฑเบ™? เบชเบปเบกเบกเบธเบ”เบงเปˆเบฒเบœเบนเป‰เบฎเบฑเบšเปƒเบŠเป‰เบขเบทเบ™เบขเบนเปˆเบ‚เป‰เบฒเบ‡เบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒ, เบœเบนเป‰เบ—เบตเปˆเบญเบฐเบ™เบธเบเบฒเบ”เปƒเบซเป‰เบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒเบ„เบปเบ™เปƒเบ”เบ„เบปเบ™เบซเบ™เบถเปˆเบ‡เป€เบญเบปเบฒเบชเป‰เบญเบก. เป€เบฎเบฑเบ”เปเบ™เบงเปƒเบ”เบžเบงเบเป€เบฎเบปเบฒเป€เบฎเบฑเบ”เปƒเบซเป‰ waiter เบ™เบตเป‰เปเบฅเบฐ philosophers เบˆเบฐเบ–เบฒเบกเป€เบ‚เบปเบฒ, เบ„เปเบฒเบ–เบฒเบกเปเบกเปˆเบ™เบซเบ™เป‰เบฒเบชเบปเบ™เปƒเบˆ.

เบงเบดเบ—เบตเบ—เบตเปˆเบ‡เปˆเบฒเบเบ”เบฒเบเบ—เบตเปˆเบชเบธเบ”เปเบกเปˆเบ™เป€เบงเบฅเบฒเบ—เบตเปˆเบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒเบžเบฝเบ‡เปเบ•เปˆเบˆเบฐเบ‚เปเปƒเบซเป‰เบœเบนเป‰เบฎเบฑเบšเปƒเบŠเป‰เบขเบนเปˆเบชเบฐเป€เบซเบกเบตเบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เป€เบ‚เบปเป‰เบฒเป€เบ–เบดเบ‡เบชเป‰เบญเบก. เป€เบซเบผเบปเปˆเบฒเบ™เบฑเป‰เบ™. เปƒเบ™เบ›เบฑเบ”เบˆเบธเบšเบฑเบ™เบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒเบˆเบฐเบšเปเปˆเบฅเปเบ–เป‰เบฒเบชเปเบฒเบฅเบฑเบšเบชเป‰เบญเบกเบขเบนเปˆเปƒเบเป‰เป†, เปเบ•เปˆเบฅเปเบ–เป‰เบฒเบซเบผเบทเบ–เบฒเบกเบœเบนเป‰เบฅเปเบ–เป‰เบฒ. เปƒเบ™เบ•เบญเบ™เบ—เปเบฒเบญเบดเบ”, เบžเบงเบเป€เบฎเบปเบฒเปƒเบŠเป‰เบžเบฝเบ‡เปเบ•เปˆ User Space เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ™เบตเป‰, เปƒเบ™เบกเบฑเบ™เบžเบงเบเป€เบฎเบปเบฒเบšเปเปˆเปƒเบŠเป‰เบเบฒเบ™เบ‚เบฑเบ”เบ‚เบงเบฒเบ‡เป€เบžเบทเปˆเบญเป‚เบ—เบซเบฒเบ‚เบฑเป‰เบ™เบ•เบญเบ™เปƒเบ”เป†เบˆเบฒเบเปเบเปˆเบ™ (เบเปˆเบฝเบงเบเบฑเบšเบžเบงเบเบกเบฑเบ™เบ‚เป‰เบฒเบ‡เบฅเบธเปˆเบกเบ™เบตเป‰).

เบเบฒเบ™เปเบเป‰เป„เบ‚เปƒเบ™เบžเบทเป‰เบ™เบ—เบตเปˆเบœเบนเป‰เปƒเบŠเป‰

เปƒเบ™เบ—เบตเปˆเบ™เบตเป‰เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเป€เบฎเบฑเบ”เป€เบŠเบฑเปˆเบ™เบ”เบฝเบงเบเบฑเบ™เบเบฑเบšเบžเบงเบเป€เบฎเบปเบฒเป€เบ„เบตเบเป€เบฎเบฑเบ”เบเบฑเบšเบซเบ™เบถเปˆเบ‡เบชเป‰เบญเบกเปเบฅเบฐเบชเบญเบ‡เบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒ, เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐ spin เปƒเบ™เบงเบปเบ‡เบˆเบญเบ™เปเบฅเบฐเบฅเปเบ–เป‰เบฒ. เปเบ•เปˆเปƒเบ™เบ›เบฑเบ”เบˆเบธเบšเบฑเบ™เบกเบฑเบ™เบˆเบฐเป€เบ›เบฑเบ™เบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒเบ—เบฑเบ‡เบซเบกเบปเบ”เปเบฅเบฐ, เบ”เบฑเปˆเบ‡เบ—เบตเปˆเบกเบฑเบ™เปเบกเปˆเบ™, เบžเบฝเบ‡เปเบ•เปˆเบซเบ™เบถเปˆเบ‡เบชเป‰เบญเบก, i.e. เบกเบฑเบ™เบชเบฒเบกเบฒเบ”เป€เบงเบปเป‰เบฒเป„เบ”เป‰เบงเปˆเบฒเบกเบตเบžเบฝเบ‡เปเบ•เปˆเบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒเบ—เบตเปˆเป€เบญเบปเบฒ "เบชเป‰เบญเบกเบ—เบญเบ‡" เบ™เบตเป‰เบˆเบฒเบ waiter เบ—เบตเปˆเบˆเบฐเบเบดเบ™เบญเบฒเบซเบฒเบ™. เบชเปเบฒเบฅเบฑเบšเบ™เบตเป‰เบžเบงเบเป€เบฎเบปเบฒเปƒเบŠเป‰ SpinLock.

private static SpinLock spinLock = new SpinLock();  // ะะฐัˆ "ะพั„ะธั†ะธะฐะฝั‚"
private void RunSpinLock(int i, CancellationToken token)
{
    while (true)
    {
        // ะ’ะทะฐะธะผะฝะฐั ะฑะปะพะบะธั€ะพะฒะบะฐ ั‡ะตั€ะตะท busy waiting. ะ’ั‹ะทั‹ะฒะฐะตะผ ะดะพ try, ั‡ั‚ะพะฑั‹
        // ะฒั‹ะฑั€ะฐัะธั‚ัŒ ะธัะบะปัŽั‡ะตะฝะธะต ะฒ ัะปัƒั‡ะฐะต ะพัˆะธะฑะบะธ ะฒ ัะฐะผะพะผ SpinLock.
        bool hasLock = false;
        spinLock.Enter(ref hasLock);
        try
        {
            // ะ—ะดะตััŒ ะผะพะถะตั‚ ะฑั‹ั‚ัŒ ั‚ะพะปัŒะบะพ ะพะดะธะฝ ะฟะพั‚ะพะบ (mutual exclusion).
            forks[Left(i)] = i + 1;  // ะ‘ะตั€ะตะผ ะฒะธะปะบัƒ ัั€ะฐะทัƒ, ะฑะตะท ะพะถะธะดะฐะฝะธั.
            forks[Right(i)] = i + 1;
            eatenFood[i] = (eatenFood[i] + 1) % (int.MaxValue - 1);
            forks[Left(i)] = 0;
            forks[Right(i)] = 0;
        }
        finally
        {
            if(hasLock) spinLock.Exit();  // ะ˜ะทะฑะตะณะฐะตะผ ะฟั€ะพะฑะปะตะผั‹ ัะพ ัะผะตั€ั‚ัŒัŽ ั„ะธะปะพัะพั„ะฐ.
        }

        Think(i);

        if (token.IsCancellationRequested)
            break;
    }
}

SpinLock เบ™เบตเป‰เปเบกเปˆเบ™เบ•เบปเบงเบชเบฐเบเบฑเบ”, เบ”เป‰เบงเบเบเบฒเบ™เป€เบงเบปเป‰เบฒเบ›เบฐเบกเบฒเบ™, เบ„เบทเบเบฑเบ™ while(true) { if (!lock) break; }, เปเบ•เปˆเบกเบต "magic" เบซเบผเบฒเบเบเบงเปˆเบฒเปƒเบ™ SpinWait (เบ—เบตเปˆเบ–เบทเบเบ™เปเบฒเปƒเบŠเป‰เบขเบนเปˆเบ—เบตเปˆเบ™เบฑเป‰เบ™). เบšเบฑเบ”โ€‹เบ™เบตเป‰โ€‹เบฅเบฒเบงโ€‹เบฎเบนเป‰โ€‹เบงเบดเบ—เบตโ€‹เบ™เบฑเบšโ€‹เบ„เบปเบ™โ€‹เบ—เบตเปˆโ€‹เบฅเปโ€‹เบ–เป‰เบฒ, เป€เบฎเบฑเบ”โ€‹เปƒเบซเป‰โ€‹เป€เบ‚เบปเบฒโ€‹เป€เบˆเบปเป‰เบฒโ€‹เบ™เบญเบ™โ€‹เปœเป‰เบญเบโ€‹เปœเบถเปˆเบ‡, เปเบฅเบฐโ€‹เบญเบทเปˆเบ™เป†. เปเบฅเบฐเบญเบทเปˆเบ™เป†. เป‚เบ”เบเบ—เบปเปˆเบงเป„เบ›, เป€เบฎเบฑเบ”เบ—เบธเบเบชเบดเปˆเบ‡เบ—เบธเบเบขเปˆเบฒเบ‡เบ—เบตเปˆเป€เบ›เบฑเบ™เป„เบ›เป„เบ”เป‰เป€เบžเบทเปˆเบญเป€เบžเบตเปˆเบกเบ›เบฐเบชเบดเบ”เบ—เบดเบžเบฒเบš. เปเบ•เปˆเบžเบงเบเป€เบฎเบปเบฒเบ•เป‰เบญเบ‡เบˆเบทเปˆเป„เบงเป‰เบงเปˆเบฒเบ™เบตเป‰เบเบฑเบ‡เบ„เบปเบ‡เป€เบ›เบฑเบ™เบงเบปเบ‡เบˆเบญเบ™เบเบฒเบ™เป€เบ„เบทเปˆเบญเบ™เป„เบซเบงเบ”เบฝเบงเบเบฑเบ™เบ—เบตเปˆเบเบดเบ™เป€เบ–เบดเบ‡เบŠเบฑเบšเบžเบฐเบเบฒเบเบญเบ™เบ‚เบญเบ‡เป‚เบ›เป€เบŠเบ”เป€เบŠเบตเปเบฅเบฐเบฎเบฑเบเบชเบฒเบเบฒเบ™เป„เบซเบผเป€เบ‚เบปเป‰เบฒ, เป€เบŠเบดเปˆเบ‡เบชเบฒเบกเบฒเบ”เบ™เปเบฒเป„เบ›เบชเบนเปˆเบ„เบงเบฒเบกเบญเบถเบ”เบซเบดเบงเบ–เป‰เบฒเบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒเบ„เบปเบ™เบซเบ™เบถเปˆเบ‡เบเบฒเบเป€เบ›เบฑเบ™เบšเบนเบฅเบดเบกเบฐเบชเบดเบ”เบซเบผเบฒเบเบเปˆเบงเบฒเบ„เบปเบ™เบญเบทเปˆเบ™, เปเบ•เปˆเบšเปเปˆเบกเบตเบชเป‰เบญเบกเบ—เบญเบ‡ (เบšเบฑเบ™เบซเบฒ Priority Inversion) . เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™, เบžเบงเบเป€เบฎเบปเบฒเปƒเบŠเป‰เบกเบฑเบ™เบžเบฝเบ‡เปเบ•เปˆเบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ›เปˆเบฝเบ™เปเบ›เบ‡เบ—เบตเปˆเบชเบฑเป‰เบ™เบซเบผเบฒเบเปƒเบ™เบซเบ™เปˆเบงเบเบ„เบงเบฒเบกเบˆเปเบฒเบ—เบตเปˆเปƒเบŠเป‰เบฎเปˆเบงเบกเบเบฑเบ™, เป‚เบ”เบเบšเปเปˆเบกเบตเบเบฒเบ™เป‚เบ—เบซเบฒเบžเบฒเบเบชเปˆเบงเบ™เบ—เบตเบชเบฒเบก, locks เบฎเบฑเบ‡, เปเบฅเบฐเบ„เบงเบฒเบกเปเบ›เบเปƒเบˆเบญเบทเปˆเบ™เป†.

Well-Fed Philosophers เบซเบผเบท Competitive .NET Programming

เปเบ•เป‰เบกเบชเปเบฒเบฅเบฑเบš SpinLock. เบชเบฒเบเบ™เป‰เปเบฒเปเบกเปˆเบ™ "เบ•เปเปˆเบชเบนเป‰" เบขเปˆเบฒเบ‡เบ•เปเปˆเป€เบ™เบทเปˆเบญเบ‡เบชเปเบฒเบฅเบฑเบšเบ„เบงเบฒเบกเบเบฒเบงเบ‚เบญเบ‡เบชเป‰เบญเบกเบ—เบญเบ‡. เบกเบตเบ„เบงเบฒเบกเบฅเบปเป‰เบกเป€เบซเบฅเบง - เปƒเบ™เบฎเบนเบš, เบžเบทเป‰เบ™เบ—เบตเปˆเบ—เบตเปˆเป€เบฅเบทเบญเบ. เบซเบผเบฑเบเบšเปเปˆเป„เบ”เป‰เบ–เบทเบเบ™เปเบฒเปƒเบŠเป‰เบขเปˆเบฒเบ‡เป€เบ•เบฑเบกเบชเปˆเบงเบ™: เบžเบฝเบ‡เปเบ•เปˆเบ›เบฐเบกเบฒเบ™ 2/3 เป‚เบ”เบเบชเบตเปˆเบเบฐเบ—เบนเป‰เป€เบซเบผเบปเปˆเบฒเบ™เบตเป‰.

เบเบฒเบ™เปเบเป‰เป„เบ‚เบญเบตเบเบญเบฑเบ™เบซเบ™เบถเปˆเบ‡เบขเบนเปˆเบ—เบตเปˆเบ™เบตเป‰เปเบกเปˆเบ™เบเบฒเบ™เบ™เปเบฒเปƒเบŠเป‰เป€เบ—เบปเปˆเบฒเบ™เบฑเป‰เบ™ Interlocked.CompareExchange เบ”เป‰เบงเบเบเบฒเบ™เบฅเปเบ–เป‰เบฒเบขเปˆเบฒเบ‡เบซเป‰เบฒเบงเบซเบฑเบ™เบ”เบฝเบงเบเบฑเบ™เบ—เบตเปˆเบชเบฐเปเบ”เบ‡เบขเบนเปˆเปƒเบ™เบฅเบฐเบซเบฑเบ”เบ‚เป‰เบฒเบ‡เป€เบ—เบดเบ‡ (เปƒเบ™เบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒเบ—เบตเปˆเบญเบถเบ”เบซเบดเบง), เปเบ•เปˆเบ™เบตเป‰, เบ”เบฑเปˆเบ‡เบ—เบตเปˆเป„เบ”เป‰เบเปˆเบฒเบงเบกเบฒเปเบฅเป‰เบง, เปƒเบ™เบ—เบฒเบ‡เบ—เบดเบ”เบชเบฐเบ”เบตเบชเบฒเบกเบฒเบ”เบ™เปเบฒเป„เบ›เบชเบนเปˆเบเบฒเบ™เบ‚เบฑเบ”เบ‚เบงเบฒเบ‡.

เบเปˆเบฝเบงเบเบฑเบš Interlocked เบ„เบงเบ™เบชเบฑเบ‡เป€เบเบ”เบงเปˆเบฒเบกเบตเบšเปเปˆเบžเบฝเบ‡เปเบ•เปˆ CompareExchange, เปเบ•เปˆเบเบฑเบ‡เบงเบดเบ—เบตเบเบฒเบ™เบญเบทเปˆเบ™เป†เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ›เบฐเบฅเปเบฒเบกเบฐเบ™เบนเบญเปˆเบฒเบ™เปเบฅเบฐเบ‚เบฝเบ™. เปเบฅเบฐเป‚เบ”เบเบœเปˆเบฒเบ™เบเบฒเบ™เบŠเป‰เปเบฒเบเบฑเบ™เบ‚เบญเบ‡เบเบฒเบ™เบ›เปˆเบฝเบ™เปเบ›เบ‡, เปƒเบ™เบเปเบฅเบฐเบ™เบตเบ—เบตเปˆเบเบฐเบ—เบนเป‰เบญเบทเปˆเบ™เบกเบตเป€เบงเบฅเบฒเบ—เบตเปˆเบˆเบฐเป€เบฎเบฑเบ”เบเบฒเบ™เบ›เปˆเบฝเบ™เปเบ›เบ‡เบ‚เบญเบ‡เบกเบฑเบ™ (เบญเปˆเบฒเบ™ 1, เบญเปˆเบฒเบ™ 2, เบ‚เบฝเบ™ 2, เบ‚เบฝเบ™ 1 เปเบกเปˆเบ™เบšเปเปˆเบ”เบต), เบกเบฑเบ™เบชเบฒเบกเบฒเบ”เบ–เบทเบเบ™เปเบฒเปƒเบŠเป‰เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ›เปˆเบฝเบ™เปเบ›เบ‡เบ—เบตเปˆเบชเบฑเบšเบชเบปเบ™เบเบฑเบšเบ„เปˆเบฒเบ”เบฝเบง (Interlocked Anything pattern) .

เบเบฒเบ™เปเบเป‰เป„เบ‚เบฎเบนเบšเปเบšเบš Kernel

เป€เบžเบทเปˆเบญเบซเบผเบตเบเป€เบงเบฑเป‰เบ™เบเบฒเบ™เบชเบนเบ™เป€เบชเบเบŠเบฑเบšเบžเบฐเบเบฒเบเบญเบ™เปƒเบ™เบงเบปเบ‡, เปƒเบซเป‰เป€เบšเบดเปˆเบ‡เบงเปˆเบฒเบžเบงเบเป€เบฎเบปเบฒเบชเบฒเบกเบฒเบ”เบšเบฅเบฑเบญเบเบเบฐเบ—เบนเป‰เป„เบ”เป‰เปเบ™เบงเปƒเบ”. เปƒเบ™เบ„เปเบฒเบชเบฑเบšเบ•เปˆเบฒเบ‡เป†เบญเบทเปˆเบ™เป†, เบชเบทเบšเบ•เปเปˆเบ•เบปเบงเบขเปˆเบฒเบ‡เบ‚เบญเบ‡เบžเบงเบเป€เบฎเบปเบฒ, เปƒเบซเป‰เบžเบงเบเป€เบฎเบปเบฒเป€เบšเบดเปˆเบ‡เบงเบดเบ—เบตเบเบฒเบ™ waiter เป€เบฎเบฑเบ”เปƒเบซเป‰ philosopher เบ™เบญเบ™เปเบฅเบฐ wakes เบฅเบฒเบงเบžเบฝเบ‡เปเบ•เปˆเปƒเบ™เป€เบงเบฅเบฒเบ—เบตเปˆเบˆเปเบฒเป€เบ›เบฑเบ™. เบ—เปเบฒเบญเบดเบ”, เปƒเบซเป‰เป€เบšเบดเปˆเบ‡เบงเบดเบ—เบตเบเบฒเบ™เป€เบฎเบฑเบ”เบชเบดเปˆเบ‡เบ™เบตเป‰เป‚เบ”เบเบœเปˆเบฒเบ™เบฎเบนเบšเปเบšเบš kernel เบ‚เบญเบ‡เบฅเบฐเบšเบปเบšเบ›เบฐเบ•เบดเบšเบฑเบ”เบเบฒเบ™. เป‚เบ„เบ‡เบชเป‰เบฒเบ‡เบ—เบฑเบ‡เบซเบกเบปเบ”เบขเบนเปˆเบ—เบตเปˆเบ™เบฑเป‰เบ™เบกเบฑเบเบˆเบฐเบŠเป‰เบฒเบเบงเปˆเบฒเบขเบนเปˆเปƒเบ™เบžเบทเป‰เบ™เบ—เบตเปˆเบ‚เบญเบ‡เบœเบนเป‰เปƒเบŠเป‰. เบ•เบปเบงเบขเปˆเบฒเบ‡เบŠเป‰เบฒเบฅเบปเบ‡เบซเบผเบฒเบเบ„เบฑเป‰เบ‡ AutoResetEvent เบญเบฒเบ”เบˆเบฐเบŠเป‰เบฒเบเบงเปˆเบฒ 53 เป€เบ—เบปเปˆเบฒ SpinLock [เบฃเบดเบเป€เบ•เบต]. เปเบ•เปˆเบ”เป‰เบงเบเบเบฒเบ™เบŠเปˆเบงเบเป€เบซเบผเบทเบญเบ‚เบญเบ‡เบžเบงเบเป€เบ‚เบปเบฒ, เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ” synchronize เบ‚เบฐเบšเบงเบ™เบเบฒเบ™เปƒเบ™เบ—เบปเปˆเบงเบฅเบฐเบšเบปเบš, เบˆเบฑเบ”เบเบฒเบ™เบซเบผเบทเบšเปเปˆ.

เบเบฒเบ™เบเปเปˆเบชเป‰เบฒเบ‡เบžเบทเป‰เบ™เบ–เบฒเบ™เบขเบนเปˆเบ—เบตเปˆเบ™เบตเป‰เปเบกเปˆเบ™ semaphore เบ—เบตเปˆเบชเบฐเป€เบซเบ™เบตเป‚เบ”เบ Dijkstra เบซเบผเบฒเบเบเบงเปˆเบฒเป€เบ„เบดเปˆเบ‡เบซเบ™เบถเปˆเบ‡เบชเบฐเบ•เบฐเบงเบฑเบ”เบเปˆเบญเบ™เบซเบ™เป‰เบฒเบ™เบตเป‰. A semaphore เปเบกเปˆเบ™, เป€เบงเบปเป‰เบฒเบ‡เปˆเบฒเบเป†, เป€เบ›เบฑเบ™เบˆเปเบฒเบ™เบงเบ™เบšเบงเบเบ—เบตเปˆเบ„เบธเป‰เบกเบ„เบญเบ‡เป‚เบ”เบเบฅเบฐเบšเบปเบš, เปเบฅเบฐเบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เบชเบญเบ‡เบขเปˆเบฒเบ‡เบเปˆเบฝเบงเบเบฑเบšเบกเบฑเบ™, เป€เบžเบตเปˆเบกเปเบฅเบฐเบซเบผเบธเบ”เบฅเบปเบ‡. เบ–เป‰เบฒเบกเบฑเบ™เบซเบผเบธเบ”เบฅเบปเบ‡, เบชเบนเบ™, เบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™เบเบฐเบ—เบนเป‰เบเบฒเบ™เป‚เบ—เบˆเบฐเบ–เบทเบเบšเบฅเบฑเบญเบ. เป€เบกเบทเปˆเบญเบ•เบปเบงเป€เบฅเบเบ–เบทเบเป€เบžเบตเปˆเบกเบ‚เบถเป‰เบ™เป‚เบ”เบเบเบฐเบ—เบนเป‰ / เบ‚เบฐเบšเบงเบ™เบเบฒเบ™เบญเบทเปˆเบ™เป†เบ—เบตเปˆเบกเบตเบเบฒเบ™เป€เบ„เบทเปˆเบญเบ™เป„เบซเบง, เบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™เบเบฐเบ—เบนเป‰เบ–เบทเบเบ‚เป‰เบฒเบกเปเบฅเบฐ semaphore เบ–เบทเบเบซเบผเบธเบ”เบฅเบปเบ‡เบญเบตเบเป€เบ—เบทเปˆเบญเบซเบ™เบถเปˆเบ‡เป‚เบ”เบเบˆเปเบฒเบ™เบงเบ™เบ—เบตเปˆเบœเปˆเบฒเบ™. เบ„เบปเบ™เป€เบฎเบปเบฒเบชเบฒเบกเบฒเบ”เบˆเบดเบ™เบ•เบฐเบ™เบฒเบเบฒเบ™เบฅเบปเบ”เป„เบŸเบขเบนเปˆเปƒเบ™เบ„เปเบ‚เบงเบ”เบ—เบตเปˆเบกเบต semaphore. .NET เบชเบฐเป€เบซเบ™เบตเป‚เบ„เบ‡เบชเป‰เบฒเบ‡เบซเบผเบฒเบเบขเปˆเบฒเบ‡เบ—เบตเปˆเบกเบตเบซเบ™เป‰เบฒเบ—เบตเปˆเบ„เป‰เบฒเบเบ„เบทเบเบฑเบ™: AutoResetEvent, ManualResetEvent, Mutex เปเบฅเบฐเบ•เบปเบงเบ‚เป‰เบญเบเป€เบญเบ‡ Semaphore. เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเบ™เปเบฒเปƒเบŠเป‰ AutoResetEvent, เบ™เบตเป‰เปเบกเปˆเบ™เบ‡เปˆเบฒเบเบ”เบฒเบเบ—เบตเปˆเบชเบธเบ”เบ‚เบญเบ‡เบเบฒเบ™เบเปเปˆเบชเป‰เบฒเบ‡เป€เบซเบผเบปเปˆเบฒเบ™เบตเป‰: เบžเบฝเบ‡เปเบ•เปˆเบชเบญเบ‡เบ„เปˆเบฒ 0 เปเบฅเบฐ 1 (false, true). เบงเบดเบ—เบตเบเบฒเบ™เบ‚เบญเบ‡เบ™เบฒเบ‡ WaitOne() เบšเบฅเบฑเบญเบเบเบฐเบ—เบนเป‰เบเบฒเบ™เป‚เบ—เบ–เป‰เบฒเบ„เปˆเบฒเปเบกเปˆเบ™ 0, เปเบฅเบฐเบ–เป‰เบฒ 1, เบซเบผเบธเบ”เบฅเบปเบ‡เป€เบ›เบฑเบ™ 0 เปเบฅเบฐเบ‚เป‰เบฒเบกเบกเบฑเบ™. เบงเบดเบ—เบตเบเบฒเบ™ Set() เป€เบžเบตเปˆเบกเบ‚เบถเป‰เบ™เป€เบ›เบฑเบ™ 1 เปเบฅเบฐเปƒเบซเป‰เบœเบนเป‰เบฎเบฑเบšเปƒเบŠเป‰เบซเบ™เบถเปˆเบ‡เบœเปˆเบฒเบ™, เบœเบนเป‰เบ—เบตเปˆเบญเบตเบเป€เบ—เบทเปˆเบญเบซเบ™เบถเปˆเบ‡เบซเบผเบธเบ”เบฅเบปเบ‡เป€เบ›เบฑเบ™ 0. เบ›เบฐเบ•เบดเบšเบฑเบ”เบ„เป‰เบฒเบเบ„เบท turnstile เบฅเบปเบ”เป„เบŸเปƒเบ•เป‰เบ”เบดเบ™.

เบ‚เปเปƒเบซเป‰เบชเบฑเบšเบชเบปเบ™เบเบฒเบ™เปเบเป‰เป„เบ‚เปเบฅเบฐเบ™เปเบฒเปƒเบŠเป‰เบฅเบฑเบญเบเบชเปเบฒเบฅเบฑเบšเบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒเปเบ•เปˆเบฅเบฐเบ„เบปเบ™, เปเบฅเบฐเบšเปเปˆเปเบกเปˆเบ™เบชเปเบฒเบฅเบฑเบšเบ—เบฑเบ‡เบซเบกเบปเบ”เปƒเบ™เป€เบงเบฅเบฒเบ”เบฝเบงเบเบฑเบ™. เป€เบซเบผเบปเปˆเบฒเบ™เบฑเป‰เบ™. เปƒเบ™เบ›เบฑเบ”เบˆเบธเบšเบฑเบ™เบชเบฒเบกเบฒเบ”เบกเบตเบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒเบซเบผเบฒเบเบ„เบปเบ™เปƒเบ™เป€เบงเบฅเบฒเบ”เบฝเบงเบเบฑเบ™, เปเบฅเบฐเบšเปเปˆเปเบกเปˆเบ™เบซเบ™เบถเปˆเบ‡. เปเบ•เปˆเบžเบงเบเป€เบฎเบปเบฒเบญเบตเบเป€เบ—เบทเปˆเบญเบซเบ™เบถเปˆเบ‡เบ•เบฑเบ™เบเบฒเบ™เป€เบ‚เบปเป‰เบฒเป€เบ–เบดเบ‡เบ•เบฒเบ•เบฐเบฅเบฒเบ‡เป€เบžเบทเปˆเบญเปƒเบซเป‰เบ–เบทเบเบ•เป‰เบญเบ‡, เบซเบผเบตเบเป€เบงเบฑเป‰เบ™เบเบฒเบ™เป€เบŠเบทเป‰เบญเบŠเบฒเบ” (เป€เบ‡เบทเปˆเบญเบ™เป„เบ‚เป€เบŠเบทเป‰เบญเบŠเบฒเบ”), เปƒเบซเป‰เปเบ™เปˆเปƒเบˆเบงเปˆเบฒเบเบฒเบ™bets.

// ะ”ะปั ะฑะปะพะบะธั€ะพะฒะฐะฝะธั ะพั‚ะดะตะปัŒะฝะพะณะพ ั„ะธะปะพัะพั„ะฐ.
// ะ˜ะฝะธั†ะธะฐะปะธะทะธั€ัƒะตั‚ัั: new AutoResetEvent(true) ะดะปั ะบะฐะถะดะพะณะพ.
private AutoResetEvent[] philosopherEvents;

// ะ”ะปั ะดะพัั‚ัƒะฟะฐ ะบ ะฒะธะปะบะฐะผ / ะดะพัั‚ัƒะฟ ะบ ัั‚ะพะปัƒ.
private AutoResetEvent tableEvent = new AutoResetEvent(true);

// ะ ะพะถะดะตะฝะธะต ั„ะธะปะพัะพั„ะฐ.
public void Run(int i, CancellationToken token)
{
    while (true)
    {
        TakeForks(i); // ะ–ะดะตั‚ ะฒะธะปะบะธ.
        // ะžะฑะตะด. ะœะพะถะตั‚ ะฑั‹ั‚ัŒ ะธ ะดะพะปัŒัˆะต.
        eatenFood[i] = (eatenFood[i] + 1) % (int.MaxValue - 1);
        PutForks(i); // ะžั‚ะดะฐั‚ัŒ ะฒะธะปะบะธ ะธ ั€ะฐะทะฑะปะพะบะธั€ะพะฒะฐั‚ัŒ ัะพัะตะดะตะน.
        Think(i);
        if (token.IsCancellationRequested) break;
    }
}

// ะžะถะธะดะฐั‚ัŒ ะฒะธะปะบะธ ะฒ ะฑะปะพะบะธั€ะพะฒะบะต.
void TakeForks(int i)
{
    bool hasForks = false;
    while (!hasForks) // ะŸะพะฟั€ะพะฑะพะฒะฐั‚ัŒ ะตั‰ะต ั€ะฐะท (ะฑะปะพะบะธั€ะพะฒะบะฐ ะฝะต ะทะดะตััŒ).
    {
        // ะ˜ัะบะปัŽั‡ะฐัŽั‰ะธะน ะดะพัั‚ัƒะฟ ะบ ัั‚ะพะปัƒ, ะฑะตะท ะณะพะฝะพะบ ะทะฐ ะฒะธะปะบะฐะผะธ.
        tableEvent.WaitOne();
        if (forks[Left(i)] == 0 && forks[Right(i)] == 0)
            forks[Left(i)] = forks[Right(i)] = i + 1;
        hasForks = forks[Left(i)] == i + 1 && forks[Right(i)] == i + 1;
        if (hasForks)
            // ะขะตะฟะตั€ัŒ ั„ะธะปะพัะพั„ ะฟะพะตัั‚, ะฒั‹ะนะดะตั‚ ะธะท ั†ะธะบะปะฐ. ะ•ัะปะธ Set 
            // ะฒั‹ะทะฒะฐะฝ ะดะฒะฐะถะดั‹, ั‚ะพ ะทะฝะฐั‡ะตะฝะธะต true.
            philosopherEvents[i].Set();
        // ะ ะฐะทะฑะปะพะบะธั€ะพะฒะฐั‚ัŒ ะพะดะฝะพะณะพ ะพะถะธะดะฐัŽั‰ะตะณะพ. ะŸะพัะปะต ะฝะตะณะพ ะทะฝะฐั‡ะตะฝะธะต tableEvent ะฒ false.
        tableEvent.Set(); 
        // ะ•ัะปะธ ะธะผะตะตั‚ true, ะฝะต ะฑะปะพะบะธั€ัƒะตั‚ัั, ะฐ ะตัะปะธ false, ั‚ะพ ะฑัƒะดะตั‚ ะถะดะฐั‚ัŒ Set ะพั‚ ัะพัะตะดะฐ.
        philosopherEvents[i].WaitOne();
    }
}

// ะžั‚ะดะฐั‚ัŒ ะฒะธะปะบะธ ะธ ั€ะฐะทะฑะปะพะบะธั€ะพะฒะฐั‚ัŒ ัะพัะตะดะตะน.
void PutForks(int i)
{
    tableEvent.WaitOne(); // ะ‘ะตะท ะณะพะฝะพะบ ะทะฐ ะฒะธะปะบะฐะผะธ.
    forks[Left(i)] = 0;
    // ะŸั€ะพะฑัƒะดะธั‚ัŒ ะปะตะฒะพะณะพ, ะฐ ะฟะพั‚ะพะผ ะธ ะฟั€ะฐะฒะพะณะพ ัะพัะตะดะฐ, ะปะธะฑะพ AutoResetEvent ะฒ true.
    philosopherEvents[LeftPhilosopher(i)].Set();
    forks[Right(i)] = 0;
    philosopherEvents[RightPhilosopher(i)].Set();
    tableEvent.Set();
}

เป€เบžเบทเปˆเบญเป€เบ‚เบปเป‰เบฒเปƒเบˆเบชเบดเปˆเบ‡เบ—เบตเปˆเป€เบเบตเบ”เบ‚เบถเป‰เบ™เบขเบนเปˆเบ—เบตเปˆเบ™เบตเป‰, เบžเบดเบˆเบฒเบฅเบฐเบ™เบฒเบเปเบฅเบฐเบ™เบตเบ—เบตเปˆเบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒเบฅเบปเป‰เบกเป€เบซเบฅเบงเปƒเบ™เบเบฒเบ™เบชเป‰เบญเบกเปเบŠเบก, เบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™เบเบฒเบ™เบเบฐเบ—เปเบฒเบ‚เบญเบ‡เบฅเบฒเบงเบˆเบฐเป€เบ›เบฑเบ™เบ”เบฑเปˆเบ‡เบ•เปเปˆเป„เบ›เบ™เบตเป‰. เบฅเบฒเบงเบเปเบฒเบฅเบฑเบ‡เบฅเปเบ–เป‰เบฒเบเบฒเบ™เป€เบ‚เบปเป‰เบฒเป€เบ–เบดเบ‡เบ•เบฒเบ•เบฐเบฅเบฒเบ‡. เป€เบกเบทเปˆเบญเป„เบ”เป‰เบฎเบฑเบšเบกเบฑเบ™, เบฅเบฒเบงเบžเบฐเบเบฒเบเบฒเบกเป€เบญเบปเบฒเบชเป‰เบญเบก. เบšเปเปˆเป„เบ”เป‰เบœเบปเบ™. เบกเบฑเบ™เปƒเบซเป‰เบเบฒเบ™เป€เบ‚เบปเป‰เบฒเป€เบ–เบดเบ‡เบ•เบฒเบ•เบฐเบฅเบฒเบ‡ (เบเบฒเบ™เบเบปเบเป€เบงเบฑเป‰เบ™เป€เบŠเบดเปˆเบ‡เบเบฑเบ™เปเบฅเบฐเบเบฑเบ™). เปเบฅเบฐเบœเปˆเบฒเบ™ "turnstile" เบ‚เบญเบ‡เบฅเบฒเบง (AutoResetEvent) (เบžเบงเบเป€เบ‚เบปเบฒเป€เบ›เบตเบ”เปƒเบ™เป€เบšเบทเป‰เบญเบ‡เบ•เบปเป‰เบ™). เบกเบฑเบ™เป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™เบงเบปเบ‡เบˆเบญเบ™เบญเบตเบเป€เบ—เบทเปˆเบญเบซเบ™เบถเปˆเบ‡, เป€เบžเบฒเบฐเบงเปˆเบฒ เบฅเบฒเบงเบšเปเปˆเบกเบตเบชเป‰เบญเบก. เบฅเบฒเบงเบžเบฐเบเบฒเบเบฒเบกเป€เบญเบปเบฒเบžเบงเบเบกเบฑเบ™เปเบฅเบฐเบขเบธเบ”เบขเบนเปˆ "turnstile" เบ‚เบญเบ‡เบฅเบฒเบง. เบšเบฒเบ‡เบ›เบฐเป€เบ—เบ”เป€เบžเบทเปˆเบญเบ™เบšเป‰เบฒเบ™เบ—เบตเปˆเป‚เบŠเบเบ”เบตเบซเบผเบฒเบเบ—เบฒเบ‡เบ”เป‰เบฒเบ™เบ‚เบงเบฒเบซเบผเบทเบŠเป‰เบฒเบ, เบเบดเบ™เบญเบฒเบซเบฒเบ™เบชเปเบฒเป€เบฅเบฑเบ”เบฎเบนเบš, เบ›เบปเบ”เบฅเบฑเบญเบเบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒเบ‚เบญเบ‡เบžเบงเบเป€เบฎเบปเบฒ, "เป€เบ›เบตเบ” turnstile เบฅเบฒเบง." เบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒเบ‚เบญเบ‡เบžเบงเบเป€เบฎเบปเบฒเบœเปˆเบฒเบ™เบกเบฑเบ™ (เปเบฅเบฐเบกเบฑเบ™เบ›เบดเบ”เบขเบนเปˆเบซเบฅเบฑเบ‡เบกเบฑเบ™) เป€เบ›เบฑเบ™เบ„เบฑเป‰เบ‡เบ—เบตเบชเบญเบ‡. เบฅเบฒเบงเบžเบฐเบเบฒเบเบฒเบกเป€เบ›เบฑเบ™เบ„เบฑเป‰เบ‡เบ—เบตเบชเบฒเบกเป€เบžเบทเปˆเบญเป€เบญเบปเบฒเบชเป‰เบญเบก. เป‚เบŠเบโ€‹เบ”เบต. เปเบฅเบฐเบฅเบฒเบงเบœเปˆเบฒเบ™ turnstile เบฅเบฒเบงเป€เบžเบทเปˆเบญเบฎเบฑเบšเบ›เบฐเบ—เบฒเบ™เบญเบฒเบซเบฒเบ™.

เป€เบกเบทเปˆเบญเบกเบตเบ‚เปเป‰เบœเบดเบ”เบžเบฒเบ”เปเบšเบšเบชเบธเปˆเบกเปƒเบ™เบฅเบฐเบซเบฑเบ”เบ”เบฑเปˆเบ‡เบเปˆเบฒเบง (เบžเบงเบเบกเบฑเบ™เบกเบตเบขเบนเปˆเบชเบฐเป€เบซเบกเบต), เบ•เบปเบงเบขเปˆเบฒเบ‡, เป€เบžเบทเปˆเบญเบ™เบšเป‰เบฒเบ™เบ–เบทเบเบฅเบฐเบšเบธเบšเปเปˆเบ–เบทเบเบ•เป‰เบญเบ‡เบซเบผเบทเบงเบฑเบ”เบ–เบธเบ”เบฝเบงเบเบฑเบ™เบ–เบทเบเบชเป‰เบฒเบ‡เบ‚เบทเป‰เบ™. AutoResetEvent เบชเปเบฒเบฅเบฑเบšเบ—เบธเบเบ„เบปเบ™ (Enumerable.Repeat), เบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™ philosophers เบˆเบฐเป„เบ”เป‰เบฎเบฑเบšเบเบฒเบ™เบฅเปเบ–เป‰เบฒเบชเปเบฒเบฅเบฑเบšเบ™เบฑเบเบžเบฑเบ”เบ—เบฐเบ™เบฒ, เป€เบ™เบทเปˆเบญเบ‡เบˆเบฒเบเบงเปˆเบฒ เบเบฒเบ™เบŠเบญเบเบซเบฒเบ‚เปเป‰เบœเบดเบ”เบžเบฒเบ”เปƒเบ™เบฅเบฐเบซเบฑเบ”เบ”เบฑเปˆเบ‡เบเปˆเบฒเบงเปเบกเปˆเบ™เบ‚เป‰เบญเบ™เบ‚เป‰เบฒเบ‡เป€เบ›เบฑเบ™เบงเบฝเบเบ—เบตเปˆเบเบฒเบ. เบšเบฑเบ™เบซเบฒเบญเบตเบเบญเบฑเบ™เบซเบ™เบถเปˆเบ‡เบ‚เบญเบ‡เบเบฒเบ™เปเบเป‰เป„เบ‚เบ™เบตเป‰เปเบกเปˆเบ™เบงเปˆเบฒเบกเบฑเบ™เบšเปเปˆเบฎเบฑเบšเบ›เบฐเบเบฑเบ™เบงเปˆเบฒเบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒเบšเบฒเบ‡เบ„เบปเบ™เบˆเบฐเบšเปเปˆเบซเบดเบง.

เบงเบดเบ—เบตเปเบเป‰เป„เบ‚เปเบšเบšเบ›เบฐเบชเบปเบก

เบžเบงเบเป€เบฎเบปเบฒเป„เบ”เป‰เป€เบšเบดเปˆเบ‡เบชเบญเบ‡เบงเบดเบ—เบตเบเบฒเบ™เบเปเบฒเบ™เบปเบ”เป€เบงเบฅเบฒ, เปƒเบ™เป€เบงเบฅเบฒเบ—เบตเปˆเบžเบงเบเป€เบฎเบปเบฒเบขเบนเปˆเปƒเบ™เป‚เบซเบกเบ”เบœเบนเป‰เปƒเบŠเป‰เปเบฅเบฐ loop, เปเบฅเบฐเปƒเบ™เป€เบงเบฅเบฒเบ—เบตเปˆเบžเบงเบเป€เบฎเบปเบฒเบ•เบฑเบ™ thread เบœเปˆเบฒเบ™ kernel. เบงเบดเบ—เบตเบ—เปเบฒเบญเบดเบ”เปเบกเปˆเบ™เบ”เบตเบชเปเบฒเบฅเบฑเบš locks เบชเบฑเป‰เบ™, เบ—เบตเบชเบญเบ‡เบชเปเบฒเบฅเบฑเบšเบเบฒเบง. เบกเบฑเบ™เบกเบฑเบเบˆเบฐเบกเบตเบ„เบงเบฒเบกเบˆเปเบฒเป€เบ›เบฑเบ™เบ—เปเบฒเบญเบดเบ”เบฅเปเบ–เป‰เบฒเป„เบฅเบเบฐเบชเบฑเป‰เบ™เป†เบชเปเบฒเบฅเบฑเบšเบ•เบปเบงเปเบ›เบ—เบตเปˆเบกเบตเบเบฒเบ™เบ›เปˆเบฝเบ™เปเบ›เบ‡เปƒเบ™ loop, เปเบฅเบฐเบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™เบชเบฐเบเบฑเบ” thread เปƒเบ™เป€เบงเบฅเบฒเบ—เบตเปˆเบฅเปเบ–เป‰เบฒเปเบกเปˆเบ™เบเบฒเบง. เบงเบดเบ—เบตเบเบฒเบ™เบ™เบตเป‰เปเบกเปˆเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เปƒเบ™เบญเบฑเบ™เบ—เบตเปˆเป€เบญเบตเป‰เบ™เบงเปˆเบฒ. เป‚เบ„เบ‡เบชเป‰เบฒเบ‡เบ›เบฐเบชเบปเบก. เบ™เบตเป‰เปเบกเปˆเบ™เป‚เบ„เบ‡เบชเป‰เบฒเบ‡เบ”เบฝเบงเบเบฑเบ™เบเบฑเบšเป‚เบซเบกเบ” kernel, เปเบ•เปˆเบ•เบญเบ™เบ™เบตเป‰เบกเบตเบฎเบนเบšเปเบšเบšเบœเบนเป‰เปƒเบŠเป‰: SemaphorSlim, ManualResetEventSlim เปเบฅเบฐเบญเบทเปˆเบ™เป† เบเบฒเบ™เบญเบญเบเปเบšเบšเบ—เบตเปˆเบ™เบดเบเบปเบกเบซเบผเบฒเบเบ—เบตเปˆเบชเบธเบ”เบขเบนเปˆเบ—เบตเปˆเบ™เบตเป‰เปเบกเปˆเบ™ Monitor, เป€เบ™เบทเปˆเบญเบ‡เบˆเบฒเบเบงเปˆเบฒ เปƒเบ™ C # เบกเบตเบŠเบทเปˆเบชเบฝเบ‡ lock syntax. Monitor เบ™เบตเป‰เปเบกเปˆเบ™ semaphore เบ”เบฝเบงเบเบฑเบ™เบเบฑเบšเบ„เปˆเบฒเบชเบนเบ‡เบชเบธเบ”เบ‚เบญเบ‡ 1 (mutex), เปเบ•เปˆเบชเบฐเบซเบ™เบฑเบšเบชเบฐเบซเบ™เบนเบ™เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบฅเปเบ–เป‰เบฒเปƒเบ™ loop, recursion, เบฎเบนเบšเปเบšเบšเบเบฒเบ™เบ›เปˆเบฝเบ™เปเบ›เบ‡เป€เบ‡เบทเปˆเบญเบ™เป„เบ‚ (เป€เบžเบตเปˆเบกเป€เบ•เบตเบกเบเปˆเบฝเบงเบเบฑเบšเบงเปˆเบฒเบ‚เป‰เบฒเบ‡เบฅเบธเปˆเบกเบ™เบตเป‰), เปเบฅเบฐเบญเบทเปˆเบ™เป†. เปƒเบซเป‰เบžเบงเบเป€เบฎเบปเบฒเป€เบšเบดเปˆเบ‡เบเบฒเบ™เปเบเป‰เป„เบ‚เบเบฑเบšเบกเบฑเบ™.

// ะกะฟั€ัั‡ะตะผ ะพะฑัŠะตะบั‚ ะดะปั ะœะพะฝะธั‚ะพั€ะฐ ะพั‚ ะฒัะตั…, ั‡ั‚ะพะฑั‹ ะฑะตะท ะดะตะดะปะพะบะพะฒ.
private readonly object _lock = new object();
// ะ’ั€ะตะผั ะพะถะธะดะฐะฝะธั ะฟะพั‚ะพะบะฐ.
private DateTime?[] _waitTimes = new DateTime?[philosophersAmount];

public void Run(int i, CancellationToken token)
{
    while (true)
    {
        TakeForks(i);
        eatenFood[i] = (eatenFood[i] + 1) % (int.MaxValue - 1);
        PutForks(i);
        Think(i);
        if (token.IsCancellationRequested) break;
    }
}

// ะะฐัˆะต ัะปะพะถะฝะพะต ัƒัะปะพะฒะธะต ะดะปั Condition Variable ะฟะฐั‚ั‚ะตั€ะฝะฐ.
bool CanIEat(int i)
{
    // ะ•ัะปะธ ะตัั‚ัŒ ะฒะธะปะบะธ:
    if (forks[Left(i)] != 0 && forks[Right(i)] != 0)
        return false;
    var now = DateTime.Now;
    // ะœะพะถะตั‚, ะตัะปะธ ัะพัะตะดะธ ะฝะต ะฑะพะปะตะต ะณะพะปะพะดะฝั‹ะต, ั‡ะตะผ ั‚ะตะบัƒั‰ะธะน.
    foreach(var p in new int[] {LeftPhilosopher(i), RightPhilosopher(i)})
        if (_waitTimes[p] != null && now - _waitTimes[p] > now - _waitTimes[i])
            return false;
    return true;
}

void TakeForks(int i)
{
    // ะ—ะฐะนั‚ะธ ะฒ ะœะพะฝะธั‚ะพั€. ะขะพ ะถะต ัะฐะผะพะต: lock(_lock) {..}.
    // ะ’ั‹ะทั‹ะฒะฐะตะผ ะฒะฝะต try, ั‡ั‚ะพะฑั‹ ะฒะพะทะผะพะถะฝะพะต ะธัะบะปัŽั‡ะตะฝะธะต ะฒั‹ะฑั€ะฐัั‹ะฒะฐะปะพััŒ ะฒั‹ัˆะต.
    bool lockTaken = false;
    Monitor.Enter(_lock, ref lockTaken);
    try
    {
        _waitTimes[i] = DateTime.Now;
        // Condition Variable ะฟะฐั‚ั‚ะตั€ะฝ. ะžัะฒะพะฑะพะถะดะฐะตะผ ะปะพะบ, ะตัะปะธ ะฝะต ะฒั‹ะฟะพะปะฝะตะฝะฝะพ 
        // ัะปะพะถะฝะพะต ัƒัะปะพะฒะธะต. ะ˜ ะถะดะตะผ ะฟะพะบะฐ ะบั‚ะพ-ะฝะธะฑัƒะดัŒ ัะดะตะปะฐะตั‚ Pulse / PulseAll.
        while (!CanIEat(i))
            Monitor.Wait(_lock); 
        forks[Left(i)] = i + 1;
        forks[Right(i)] = i + 1;
        _waitTimes[i] = null;
    }
    finally
    {
        if (lockTaken) Monitor.Exit(_lock);
    }
}

void PutForks(int i)
{
    // ะขะพ ะถะต ัะฐะผะพะต: lock (_lock) {..}.
    bool lockTaken = false;
    Monitor.Enter(_lock, ref lockTaken);
    try
    {
        forks[Left(i)] = 0;
        forks[Right(i)] = 0;
        // ะžัะฒะพะฑะพะดะธั‚ัŒ ะฒัะต ะฟะพั‚ะพะบะธ ะฒ ะพั‡ะตั€ะตะดะธ ะŸะžะกะ›ะ• ะฒั‹ะทะพะฒะฐ Monitor.Exit.
        Monitor.PulseAll(_lock); 
    }
    finally
    {
        if (lockTaken) Monitor.Exit(_lock);
    }
}

เบญเบตเบเป€เบ—เบทเปˆเบญเปœเบถเปˆเบ‡เบžเบงเบเป€เบฎเบปเบฒเบ›เบดเบ”เบเบฑเป‰เบ™เป‚เบ•เบฐเบ—เบฑเบ‡เปเบปเบ”เป€เบžเบทเปˆเบญเป€เบ‚เบปเป‰เบฒเบซเบฒเบชเป‰เบญเบก, เปเบ•เปˆเบ•เบญเบ™เบ™เบตเป‰เบžเบงเบเป€เบฎเบปเบฒเบเบณเบฅเบฑเบ‡เบ›เบปเบ”เบšเบฅเบฑเบญเบเบ—เบธเบเบซเบปเบงเบ‚เปเป‰เปƒเบ™เป€เบ—เบทเปˆเบญเบ”เบฝเบง, เปเบฅเบฐเบšเปเปˆเปเบกเปˆเบ™เป€เบžเบทเปˆเบญเบ™เบšเป‰เบฒเบ™เป€เบกเบทเปˆเบญเบกเบตเบ„เบปเบ™เบเบดเบ™เป€เบ‚เบปเป‰เบฒเปเบฅเป‰เบง. เป€เบซเบผเบปเปˆเบฒเบ™เบฑเป‰เบ™. เบ—เปเบฒเบญเบดเบ”, เบกเบตเบ„เบปเบ™เบเบดเบ™เปเบฅเบฐเบ•เบฑเบ™เบ›เบฐเป€เบ—เบ”เป€เบžเบทเปˆเบญเบ™เบšเป‰เบฒเบ™, เปเบฅเบฐเปƒเบ™เป€เบงเบฅเบฒเบ—เบตเปˆเบ„เบปเบ™เบ™เบตเป‰เบชเปเบฒเป€เบฅเบฑเบ”, เปเบ•เปˆเบ•เป‰เบญเบ‡เบเบฒเบ™เบ—เบตเปˆเบˆเบฐเบเบดเบ™เบญเบฒเบซเบฒเบ™เบญเบตเบเป€เบ—เบทเปˆเบญเบซเบ™เบถเปˆเบ‡เบ—เบฑเบ™เบ—เบต, เบฅเบฒเบงเป€เบ‚เบปเป‰เบฒเป„เบ›เปƒเบ™เบ•เบฑเบ™เปเบฅเบฐเบ›เบธเบเป€เบžเบทเปˆเบญเบ™เบšเป‰เบฒเบ™เบ‚เบญเบ‡เบ•เบปเบ™, เป€เบžเบฒเบฐเบงเปˆเบฒ. เป€เบงเบฅเบฒเบฅเปเบ–เป‰เบฒเบ‚เบญเบ‡เบกเบฑเบ™เบซเบ™เป‰เบญเบเบฅเบปเบ‡.

เบ™เบตเป‰โ€‹เบ„เบทโ€‹เบงเบดเบ—เบตโ€‹เบ—เบตเปˆโ€‹เบžเบงเบโ€‹เป€เบฎเบปเบฒโ€‹เบซเบผเบตเบโ€‹เบฅเปˆเบฝเบ‡โ€‹เบเบฒเบ™โ€‹เบ›เบดเบ”โ€‹เบฅเป‰เบญเบกโ€‹เปเบฅเบฐโ€‹เบ„เบงเบฒเบกโ€‹เบญเบถเบ”เบขเบฒเบโ€‹เบ‚เบญเบ‡โ€‹เบ™เบฑเบโ€‹เบ›เบฑเบ”เบŠเบฐเบเบฒโ€‹เบšเบฒเบ‡โ€‹เบ„เบปเบ™. เบžเบงเบเป€เบฎเบปเบฒเปƒเบŠเป‰ loop เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบฅเปเบ–เป‰เบฒเบชเบฑเป‰เบ™เปเบฅเบฐเบ•เบฑเบ™เบเบฐเบ—เบนเป‰เบชเปเบฒเบฅเบฑเบšเบเบฒเบงเบซเบ™เบถเปˆเบ‡. เบเบฒเบ™เบ›เบปเบ”เบšเบฅเบฑเบญเบเบ—เบธเบเบ„เบปเบ™เปƒเบ™เบ„เบฑเป‰เบ‡เบ”เบฝเบงเปเบกเปˆเบ™เบŠเป‰เบฒเบเบงเปˆเบฒเบ–เป‰เบฒเบžเบฝเบ‡เปเบ•เปˆเป€เบžเบทเปˆเบญเบ™เบšเป‰เบฒเบ™เบ–เบทเบเบ›เบปเบ”เบšเบฅเบฑเบญเบ, เบ„เบทเบเบฑเบšเบเบฒเบ™เปเบเป‰เป„เบ‚เบ”เป‰เบงเบ AutoResetEvent, เปเบ•เปˆเบ„เบงเบฒเบกเปเบ•เบเบ•เปˆเบฒเบ‡เบšเปเปˆเบ„เบงเบ™เบˆเบฐเบกเบตเบ‚เบฐเบซเบ™เบฒเบ”เปƒเบซเบเปˆ, เป€เบžเบฒเบฐเบงเปˆเบฒ เบเบฐเบ—เบนเป‰เบ•เป‰เบญเบ‡เบขเบนเปˆเปƒเบ™เป‚เปเบ”เบœเบนเป‰เปƒเบŠเป‰เบเปˆเบญเบ™.

ะฃ lock syntax เบกเบตเบ„เบงเบฒเบกเปเบ›เบเปƒเบˆเบ—เบตเปˆเบซเบ™เป‰เบฒเบ›เบฐเบซเบฅเบฒเบ”เปƒเบˆ. เปเบ™เบฐเบ™เปเบฒเปƒเบซเป‰เปƒเบŠเป‰ Monitor เป‚เบ”เบเบเบปเบ‡ [Richter] [Eric Lippert]. เบซเบ™เบถเปˆเบ‡เปƒเบ™เบ™เบฑเป‰เบ™เปเบกเปˆเบ™ lock เบชเบฐเป€เบซเบกเบตเบญเบญเบเบˆเบฒเบ Monitor, เป€เบ–เบดเบ‡เปเบกเปˆเบ™เบงเปˆเบฒเบกเบตเบ‚เปเป‰เบเบปเบเป€เบงเบฑเป‰เบ™, เปƒเบ™เบเปเบฅเบฐเบ™เบตเบ™เบตเป‰เบเบฐเบ—เบนเป‰เบญเบทเปˆเบ™เบชเบฒเบกเบฒเบ”เบ›เปˆเบฝเบ™เบชเบฐเบ–เบฒเบ™เบฐเบซเบ™เปˆเบงเบเบ„เบงเบฒเบกเบˆเปเบฒเบ—เบตเปˆเปƒเบŠเป‰เบฎเปˆเบงเบกเบเบฑเบ™เป„เบ”เป‰. เปƒเบ™เบเปเบฅเบฐเบ™เบตเบ”เบฑเปˆเบ‡เบเปˆเบฒเบง, เบกเบฑเบ™เบกเบฑเบเบˆเบฐเบ”เบตเบเบงเปˆเบฒเบ—เบตเปˆเบˆเบฐเป„เบ› deadlock เบซเบผเบท somehow เบขเบธเบ”เป‚เบ„เบ‡เบเบฒเบ™เบขเปˆเบฒเบ‡เบ›เบญเบ”เป„เบž. เบ„เบงเบฒเบกเปเบ›เบเปƒเบˆเบญเบตเบเบญเบฑเบ™เบซเบ™เบถเปˆเบ‡เปเบกเปˆเบ™เบงเปˆเบฒ Monitor เปƒเบŠเป‰เบ•เบฑเบ™ synchronization (SyncBlock), เป€เบŠเบดเปˆเบ‡เบกเบตเบขเบนเปˆเปƒเบ™เบงเบฑเบ”เบ–เบธเบ—เบฑเบ‡เบซเบกเบปเบ”. เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™, เบ–เป‰เบฒเป€เบฅเบทเบญเบเบงเบฑเบ”เบ–เบธเบ—เบตเปˆเบšเปเปˆเป€เบซเบกเบฒเบฐเบชเบปเบก, เป€เบˆเบปเป‰เบฒเบชเบฒเบกเบฒเบ”เบ–เบทเบเบขเบธเบ”เป„เบ”เป‰เบขเปˆเบฒเบ‡เบ‡เปˆเบฒเบเบ”เบฒเบ (เบ•เบปเบงเบขเปˆเบฒเบ‡, เบ–เป‰เบฒเป€เบˆเบปเป‰เบฒเบฅเบฑเบญเบเปƒเบชเปˆเบชเบฒเบเบ—เบตเปˆเป€เบŠเบทเปˆเบญเบกเบ•เปเปˆ). เบžเบงเบเป€เบฎเบปเบฒเปƒเบŠเป‰เบงเบฑเบ”เบ–เบธเบ—เบตเปˆเป€เบŠเบทเปˆเบญเบ‡เป„เบงเป‰เบชเบฐเป€เบซเบกเบตเบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ™เบตเป‰.

เบฎเบนเบšเปเบšเบšเบ•เบปเบงเปเบ›เบ‚เบญเบ‡เป€เบ‡เบทเปˆเบญเบ™เป„เบ‚เบŠเปˆเบงเบเปƒเบซเป‰เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เบ›เบฐเบ•เบดเบšเบฑเบ”เบ„เบงเบฒเบกเบ„เบฒเบ”เบซเบงเบฑเบ‡เบ‚เบญเบ‡เบšเบฒเบ‡เป€เบ‡เบทเปˆเบญเบ™เป„เบ‚เบ—เบตเปˆเบชเบฑเบšเบชเบปเบ™เบซเบผเบฒเบเบ‚เบทเป‰เบ™. เปƒเบ™ .NET, เบกเบฑเบ™เบšเปเปˆเบ„เบปเบšเบ–เป‰เบงเบ™, เปƒเบ™เบ„เบงเบฒเบกเบ„เบดเบ”เป€เบซเบฑเบ™เบ‚เบญเบ‡เบ‚เป‰เบญเบ, เป€เบžเบฒเบฐเบงเปˆเบฒ เปƒเบ™เบ—เบฒเบ‡เบ—เบดเบ”เบชเบฐเบ”เบต, เบ„เบงเบ™เบˆเบฐเบกเบตเบซเบผเบฒเบเป†เปเบ–เบงเบขเบนเปˆเปƒเบ™เบ•เบปเบงเปเบ›เบซเบผเบฒเบ (เป€เบŠเบฑเปˆเบ™เบ”เบฝเบงเบเบฑเบš Posix Threads), เปเบฅเบฐเบšเปเปˆเปเบกเปˆเบ™เบขเบนเปˆเปƒเบ™เบซเบ™เบถเปˆเบ‡ lok. เบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™, เบซเบ™เบถเปˆเบ‡เบชเบฒเบกเบฒเบ”เป€เบฎเบฑเบ”เปƒเบซเป‰เบžเบงเบเป€เบ‚เบปเบฒเบชเปเบฒเบฅเบฑเบš philosophers เบ—เบฑเบ‡เบซเบกเบปเบ”. เปเบ•เปˆเป€เบ–เบดเบ‡เปเบกเปˆเบ™เบงเปˆเบฒเปƒเบ™เบฎเบนเบšเปเบšเบšเบ™เบตเป‰, เบกเบฑเบ™เบญเบฐเบ™เบธเบเบฒเบ”เปƒเบซเป‰เบ—เปˆเบฒเบ™เบซเบผเบธเบ”เบœเปˆเบญเบ™เบฅเบฐเบซเบฑเบ”.

เบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒเบซเบผเบฒเบเบ„เบปเบ™เบซเบผเบท async / await

เบ•เบปเบเบฅเบปเบ‡, เบ”เบฝเบงเบ™เบตเป‰เบžเบงเบเป€เบฎเบปเบฒเบชเบฒเบกเบฒเบ”เบšเบฅเบฑเบญเบเบเบฐเบ—เบนเป‰เป„เบ”เป‰เบขเปˆเบฒเบ‡เบกเบตเบ›เบฐเบชเบดเบ”เบ—เบดเบžเบฒเบš. เปเบ•เปˆเบˆเบฐเป€เบ›เบฑเบ™เปเบ™เบงเปƒเบ”เบ–เป‰เบฒเบžเบงเบเป€เบฎเบปเบฒเบกเบตเบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒเบซเบผเบฒเบ? 100? 10000? เบ•เบปเบงเบขเปˆเบฒเบ‡, เบžเบงเบเป€เบฎเบปเบฒเป„เบ”เป‰เบฎเบฑเบšเบเบฒเบ™เบฎเป‰เบญเบ‡เบ‚เป 100000 เบเบฑเบšเป€เบ„เบทเปˆเบญเบ‡เปเบกเปˆเบ‚เปˆเบฒเบเป€เบงเบฑเบšเป„เบŠเบ•เปŒ. เบกเบฑเบ™เบˆเบฐเป€เบ›เบฑเบ™ overhead เป€เบžเบทเปˆเบญเบชเป‰เบฒเบ‡ thread เบชเปเบฒเบฅเบฑเบšเปเบ•เปˆเบฅเบฐเบ„เปเบฒเบฎเป‰เบญเบ‡เบ‚เป, เป€เบ™เบทเปˆเบญเบ‡เบˆเบฒเบเบงเปˆเบฒ เบซเบผเบฒเบเบเบฐเบ—เบนเป‰เบˆเบฐเบšเปเปˆเบ”เปเบฒเป€เบ™เบตเบ™เบเบฒเบ™เบ‚เบฐเบซเบ™เบฒเบ™. เบˆเบฐเบ”เปเบฒเป€เบ™เบตเบ™เบเบฒเบ™เบžเบฝเบ‡เปเบ•เปˆเบซเบผเบฒเบเป€เบ—เบปเปˆเบฒเบ—เบตเปˆเบกเบตเบซเบผเบฑเบเป€เบซเบ”เบœเบปเบ™ (เบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒเบกเบต 4). เปเบฅเบฐเบ„เบปเบ™เบญเบทเปˆเบ™เบžเบฝเบ‡เปเบ•เปˆเบˆเบฐเป€เบญเบปเบฒเบŠเบฑเบšเบžเบฐเบเบฒเบเบญเบ™เป„เบ›. เบซเบ™เบถเปˆเบ‡เปƒเบ™เบเบฒเบ™เปเบเป‰เป„เบ‚เบšเบฑเบ™เบซเบฒเบ™เบตเป‰เปเบกเปˆเบ™เบฎเบนเบšเปเบšเบš async / เบฅเปเบ–เป‰เบฒ. เบ„เบงเบฒเบกเบ„เบดเบ”เบ‚เบญเบ‡เบกเบฑเบ™เปเบกเปˆเบ™เบงเปˆเบฒเบซเบ™เป‰เบฒเบ—เบตเปˆเบšเปเปˆเบ–เบทเบเบฐเบ—เบนเป‰เบ–เป‰เบฒเบกเบฑเบ™เบ•เป‰เบญเบ‡เบเบฒเบ™เบฅเปเบ–เป‰เบฒเบšเบฒเบ‡เบชเบดเปˆเบ‡เบšเบฒเบ‡เบขเปˆเบฒเบ‡เบ—เบตเปˆเบˆเบฐเบชเบทเบšเบ•เปเปˆ. เปเบฅเบฐเป€เบกเบทเปˆเบญเบกเบฑเบ™เป€เบฎเบฑเบ”เบšเบฒเบ‡เบชเบดเปˆเบ‡เบšเบฒเบ‡เบขเปˆเบฒเบ‡, เบกเบฑเบ™เบชเบทเบšเบ•เปเปˆเบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ” (เปเบ•เปˆเบšเปเปˆเบˆเปเบฒเป€เบ›เบฑเบ™เบ•เป‰เบญเบ‡เบขเบนเปˆเปƒเบ™เบเบฐเบ—เบนเป‰เบ”เบฝเบงเบเบฑเบ™!). เปƒเบ™เบเปเบฅเบฐเบ™เบตเบ‚เบญเบ‡เบžเบงเบเป€เบฎเบปเบฒ, เบžเบงเบเป€เบฎเบปเบฒเบˆเบฐเบฅเปเบ–เป‰เบฒเบชเปเบฒเบฅเบฑเบšเบชเป‰เบญเบก.

SemaphoreSlim เบกเบตเบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ™เบตเป‰ WaitAsync() เบงเบดเบ—เบตเบเบฒเบ™. เบ™เบตเป‰เปเบกเปˆเบ™เบเบฒเบ™เบˆเบฑเบ”เบ•เบฑเป‰เบ‡เบ›เบฐเบ•เบดเบšเบฑเบ”เป‚เบ”เบเปƒเบŠเป‰เบฎเบนเบšเปเบšเบšเบ™เบตเป‰.

// ะ—ะฐะฟัƒัะบ ั‚ะฐะบะพะน ะถะต, ะบะฐะบ ั€ะฐะฝัŒัˆะต. ะ“ะดะต-ะฝะธะฑัƒะดัŒ ะฒ ะฟั€ะพะณั€ะฐะผะผะต:
Task.Run(() => Run(i, cancelTokenSource.Token));

// ะ—ะฐะฟัƒัะบ ั„ะธะปะพัะพั„ะฐ.
// ะšะปัŽั‡ะตะฒะพะต ัะปะพะฒะพ async -- ะบะพะผะฟะธะปัั‚ะพั€ ั‚ั€ะฐะฝัะปะธั€ัƒะตั‚ ัั‚ะพั‚ ะผะตั‚ะพั‚ ะฒ ะฐัะธะฝั…ั€ะพะฝะฝั‹ะน.
public async Task Run(int i, CancellationToken token)
{
    while (true)
    {
        // await -- ะฑัƒะดะตะผ ะพะถะธะดะฐั‚ัŒ ะบะฐะบะพะณะพ-ั‚ะพ ัะพะฑั‹ั‚ะธั.
        await TakeForks(i);
        // ะŸะพัะปะต await, ะฟั€ะพะดะพะปะถะตะฝะธะต ะฒะพะทะผะพะถะฝะพ ะฒ ะดั€ัƒะณะพะผ ะฟะพั‚ะพะบะต.
        eatenFood[i] = (eatenFood[i] + 1) % (int.MaxValue - 1);
        // ะœะพะถะตั‚ ะฑั‹ั‚ัŒ ะฝะตัะบะพะปัŒะบะพ ัะพะฑั‹ั‚ะธะน ะดะปั ะพะถะธะดะฐะฝะธั.
        await PutForks(i);

        Think(i);

        if (token.IsCancellationRequested) break;
    }
}

async Task TakeForks(int i)
{
    bool hasForks = false;
    while (!hasForks)
    {
        // ะ’ะทะฐะธะผะพะธัะบะปัŽั‡ะฐัŽั‰ะธะน ะดะพัั‚ัƒะฟ ะบ ัั‚ะพะปัƒ:
        await _tableSemaphore.WaitAsync();
        if (forks[Left(i)] == 0 && forks[Right(i)] == 0)
        {
            forks[Left(i)] = i+1;
            forks[Right(i)] = i+1;
            hasForks = true;
        }
        _tableSemaphore.Release();
        // ะ‘ัƒะดะตะผ ะพะถะธะดะฐั‚ัŒ, ั‡ั‚ะพะฑั‹ ัะพัะตะด ะฟะพะปะพะถะธะป ะฒะธะปะบะธ:
        if (!hasForks)
            await _philosopherSemaphores[i].WaitAsync();
    }
}

// ะ–ะดะตะผ ะดะพัั‚ัƒะฟะฐ ะบ ัั‚ะพะปัƒ ะธ ะบะปะฐะดะตะผ ะฒะธะปะบะธ.
async Task PutForks(int i)
{
    await _tableSemaphore.WaitAsync();
    forks[Left(i)] = 0;
    // "ะŸั€ะพะฑัƒะดะธั‚ัŒ" ัะพัะตะดะตะน, ะตัะปะธ ะพะฝะธ "ัะฟะฐะปะธ".
    _philosopherSemaphores[LeftPhilosopher(i)].Release();
    forks[Right(i)] = 0;
    _philosopherSemaphores[RightPhilosopher(i)].Release();
    _tableSemaphore.Release();
}

เบงเบดเบ—เบตเบเบฒเบ™เบเบฑเบš async / await เป„เบ”เป‰เบ–เบทเบเปเบ›เป€เบ›เบฑเบ™เป€เบ„เบทเปˆเบญเบ‡เบˆเบฑเบเบ‚เบญเบ‡เบฅเบฑเบ” tricky เบ—เบตเปˆเบ—เบฑเบ™เบ—เบตเบเบฑเบšเบ„เบทเบ™เบžเบฒเบเปƒเบ™เบ‚เบญเบ‡เบ•เบปเบ™ Task. เบœเปˆเบฒเบ™เบกเบฑเบ™, เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เบฅเปเบ–เป‰เบฒเบเบฒเบ™เบชเปเบฒเป€เบฅเบฑเบ”เบ‚เบญเบ‡เบงเบดเบ—เบตเบเบฒเบ™, เบเบปเบเป€เบฅเบตเบเบกเบฑเบ™, เปเบฅเบฐเบ—เบธเบเบชเบดเปˆเบ‡เบ—เบธเบเบขเปˆเบฒเบ‡เบ—เบตเปˆเบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เป€เบฎเบฑเบ”เป„เบ”เป‰เบเบฑเบš Task. เบžเบฒเบเปƒเบ™เบงเบดเบ—เบตเบเบฒเบ™, เป€เบ„เบทเปˆเบญเบ‡เบˆเบฑเบเบ‚เบญเบ‡เบฅเบฑเบ”เบ„เบงเบšเบ„เบธเบกเบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”. เป€เบชเบฑเป‰เบ™เบ—เบฒเบ‡เบฅเบธเปˆเบกเปเบกเปˆเบ™เบงเปˆเบฒเบ–เป‰เบฒเบšเปเปˆเบกเบตเบเบฒเบ™เบŠเบฑเบเบŠเป‰เบฒ, เบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™เบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เปเบกเปˆเบ™ synchronous, เปเบฅเบฐเบ–เป‰เบฒเบกเบต, เบซเบผเบฑเบ‡เบˆเบฒเบเบ™เบฑเป‰เบ™เบเบฐเบ—เบนเป‰เบ–เบทเบเบ›เปˆเบญเบเบญเบญเบเบกเบฒ. เบชเปเบฒเบฅเบฑเบšเบ„เบงเบฒเบกเป€เบ‚เบปเป‰เบฒเปƒเบˆเบ—เบตเปˆเบ”เบตเบเบงเปˆเบฒเบ™เบตเป‰, เบกเบฑเบ™เบเปเปˆเบ”เบตเบเบงเปˆเบฒเบ—เบตเปˆเบˆเบฐเป€เบšเบดเปˆเบ‡เป€เบ„เบทเปˆเบญเบ‡เบˆเบฑเบเบ‚เบญเบ‡เบฅเบฑเบ”เบ™เบตเป‰. เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เบชเป‰เบฒเบ‡เบ•เปˆเบญเบ‡เป‚เบชเป‰เบˆเบฒเบเป€เบซเบผเบปเปˆเบฒเบ™เบตเป‰ async / await เบงเบดเบ—เบตเบเบฒเบ™.

เปƒเบซเป‰เบ—เบปเบ”เบชเบญเบš. เบเบฒเบ™เป€เบฎเบฑเบ”เบงเบฝเบเบ‚เบญเบ‡เบ™เบฑเบเบ›เบฑเบ”เบŠเบฐเบเบฒ 100 เบ„เบปเบ™เปƒเบ™เป€เบ„เบทเปˆเบญเบ‡เบˆเบฑเบเบ—เบตเปˆเบกเบต 4 เบซเบผเบฑเบเป€เบซเบ”เบœเบปเบ™, 8 เบงเบดเบ™เบฒเบ—เบต. เบเบฒเบ™เปเบเป‰เป„เบ‚เบ—เบตเปˆเบœเปˆเบฒเบ™เบกเบฒเบเบฑเบš Monitor เบžเบฝเบ‡เปเบ•เปˆเปเบฅเปˆเบ™ 4 threads เบ—เปเบฒเบญเบดเบ”เปเบฅเบฐเบชเปˆเบงเบ™เบ—เบตเปˆเป€เบซเบผเบทเบญเบšเปเปˆเป„เบ”เป‰เบ”เปเบฒเป€เบ™เบตเบ™เบเบฒเบ™เบ—เบฑเบ‡เบซเบกเบปเบ”. เปเบ•เปˆเบฅเบฐเบเบฐเบ—เบนเป‰ 4 เบญเบฑเบ™เบ™เบตเป‰เบšเปเปˆเบกเบตเป€เบงเบฅเบฒเบ›เบฐเบกเบฒเบ™ 2ms. เปเบฅเบฐเบเบฒเบ™เปเบเป‰เป„เบ‚ async / awai เปเบฅเปˆเบ™เบ—เบฑเบ‡เบซเบกเบปเบ” 100, เบ”เป‰เบงเบเบเบฒเบ™เบฅเปเบ–เป‰เบฒเป‚เบ”เบเบชเบฐเป€เบฅเปˆเบ 6.8 เบงเบดเบ™เบฒเบ—เบตเปเบ•เปˆเบฅเบฐเบ„เบปเบ™. เปเบ™เปˆเบ™เบญเบ™, เปƒเบ™เบฅเบฐเบšเบปเบšเบ—เบตเปˆเปเบ—เป‰เบˆเบดเบ‡, idle เบชเปเบฒเบฅเบฑเบš 6 เบงเบดเบ™เบฒเบ—เบตเปเบกเปˆเบ™เบšเปเปˆเบชเบฒเบกเบฒเบ”เบเบญเบกเบฎเบฑเบšเป„เบ”เป‰เปเบฅเบฐเบกเบฑเบ™เบ”เบตเบเบงเปˆเบฒเบ—เบตเปˆเบˆเบฐเบšเปเปˆเบ”เปเบฒเป€เบ™เบตเบ™เบเบฒเบ™เบฎเป‰เบญเบ‡เบ‚เปเบˆเปเบฒเบ™เบงเบ™เบซเบผเบฒเบเป€เบŠเบฑเปˆเบ™เบ™เบตเป‰. เบเบฒเบ™เปเบเป‰เป„เบ‚เบเบฑเบš Monitor เป„เบ”เป‰เบเบฒเบเป€เบ›เบฑเบ™เบšเปเปˆเบชเบฒเบกเบฒเบ”เบ‚เบฐเบซเบเบฒเบเป„เบ”เป‰เบ—เบฑเบ‡เบซเบกเบปเบ”.

เบชเบฐเบซเบฅเบธเบš

เบ”เบฑเปˆเบ‡เบ—เบตเปˆเป€เบˆเบปเป‰เบฒเบชเบฒเบกเบฒเบ”เป€เบซเบฑเบ™เป„เบ”เป‰เบˆเบฒเบเบ•เบปเบงเบขเปˆเบฒเบ‡เบ™เป‰เบญเบเป†เป€เบซเบผเบปเปˆเบฒเบ™เบตเป‰, .NET เบชเบฐเบซเบ™เบฑเบšเบชเบฐเบซเบ™เบนเบ™เป‚เบ„เบ‡เบชเป‰เบฒเบ‡ synchronization เบซเบผเบฒเบ. เบขเปˆเบฒเบ‡เปƒเบ”เบเปเบ•เบฒเบก, เบกเบฑเบ™เบšเปเปˆเปเบกเปˆเบ™เบชเบดเปˆเบ‡เบ—เบตเปˆเบˆเบฐเปเบˆเป‰เบ‡เบชเบฐเป€เบซเบกเบตเบงเบดเบ—เบตเบเบฒเบ™เบ™เปเบฒเปƒเบŠเป‰เบžเบงเบเบกเบฑเบ™. เบ‚เป‰เบญเบเบซเบงเบฑเบ‡เบงเปˆเบฒเบšเบปเบ”เบ„เบงเบฒเบกเบ™เบตเป‰เป€เบ›เบฑเบ™เบ›เบฐเป‚เบซเบเบ”. เบชเปเบฒเบฅเบฑเบšเปƒเบ™เบ›เบฑเบ”เบˆเบธเบšเบฑเบ™, เบ™เบตเป‰เปเบกเปˆเบ™เบˆเบธเบ”เบˆเบปเบš, เปเบ•เปˆเบเบฑเบ‡เบกเบตเบชเบดเปˆเบ‡เบ—เบตเปˆเบซเบ™เป‰เบฒเบชเบปเบ™เปƒเบˆเบซเบผเบฒเบเบ—เบตเปˆเบเบฑเบ‡เป€เบซเบผเบทเบญ, เบ•เบปเบงเบขเปˆเบฒเบ‡เป€เบŠเบฑเปˆเบ™: เบเบฒเบ™เป€เบเบฑเบšเบเบฐเบ—เบนเป‰เบ—เบตเปˆเบ›เบญเบ”เป„เบž, TPL Dataflow, เบเบฒเบ™เบ‚เบฝเบ™เป‚เบ›เบผเปเบเบผเบก Reactive, เบฎเบนเบšเปเบšเบšเบเบฒเบ™เป€เบฎเบฑเบ”เบ—เบธเบฅเบฐเบเปเบฒเบŠเบญเบšเปเบง, เปเบฅเบฐเบญเบทเปˆเบ™เป†.

เปเบซเบผเปˆเบ‡เบ‚เปเป‰เบกเบนเบ™

เปเบซเบผเปˆเบ‡เบ‚เปเป‰เบกเบนเบ™: www.habr.com

เป€เบžเบตเปˆเบกเบ„เบงเบฒเบกเบ„เบดเบ”เป€เบซเบฑเบ™