Π‘ΠΈΡ‚ΠΈΡ‚Π΅ философи ΠΈΠ»ΠΈ ΠΊΠΎΠ½ΠΊΡƒΡ€Π΅Π½Ρ‚Π½ΠΎ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ€Π°Π½Π΅ Π½Π° .NET

Π‘ΠΈΡ‚ΠΈΡ‚Π΅ философи ΠΈΠ»ΠΈ ΠΊΠΎΠ½ΠΊΡƒΡ€Π΅Π½Ρ‚Π½ΠΎ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ€Π°Π½Π΅ Π½Π° .NET

НСка Π΄Π° Π²ΠΈΠ΄ΠΈΠΌ ΠΊΠ°ΠΊ Π΅ устроСно ΠΊΠΎΠ½ΠΊΡƒΡ€Π΅Π½Ρ‚Π½ΠΎΡ‚ΠΎ ΠΈ ΠΏΠ°Ρ€Π°Π»Π΅Π»Π½ΠΎΡ‚ΠΎ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ€Π°Π½Π΅ Π² .Net, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° с философитС, ΠΊΠΎΠΈΡ‚ΠΎ обядват. ΠŸΠ»Π°Π½ΡŠΡ‚ Π΅ Ρ‚Π°ΠΊΡŠΠ² - ΠΎΡ‚ синхронизация Π½Π° ΠΏΠΎΡ‚ΠΎΡ†ΠΈ/процСси Π΄ΠΎ акторски ΠΌΠΎΠ΄Π΅Π»ΠΈ (Π² слСдващитС части). Бтатията ΠΌΠΎΠΆΠ΅ Π΄Π° бъдС ΠΏΠΎΠ»Π΅Π·Π½Π° ΠΊΠ°ΠΊΡ‚ΠΎ Π·Π° ΠΏΡŠΡ€Π²ΠΈ запознанства, Ρ‚Π°ΠΊΠ° ΠΈ Π·Π° освСТаванС Π½Π° познанията.

Π—Π°Ρ‰ΠΎ Π²ΡΡŠΡ‰Π½ΠΎΡΡ‚ Π΄Π° ΡƒΠΌΠ΅Π΅ΠΌ Ρ‚ΠΎΠ²Π°? ВранзисторитС достигат минималния си Ρ€Π°Π·ΠΌΠ΅Ρ€, Π·Π°ΠΊΠΎΠ½ΡŠΡ‚ Π½Π° ΠœΡƒΡ€ достига Π³Ρ€Π°Π½ΠΈΡ†Π°, Π·Π°Π΄Π°Π΄Π΅Π½Π° ΠΎΡ‚ скоростта Π½Π° свСтлината, ΠΈ Π·Π°Ρ‚ΠΎΠ²Π° Ρ€Π°ΡΡ‚Π΅ΠΆΡŠΡ‚ сС наблюдава Π² количСството; ΠΌΠΎΠΆΠ΅ Π΄Π° сС ΠΏΡ€ΠΎΠΈΠ·Π²Π΅ΠΆΠ΄Π°Ρ‚ ΠΏΠΎΠ²Π΅Ρ‡Π΅ транзистори. Π’ ΡΡŠΡ‰ΠΎΡ‚ΠΎ Π²Ρ€Π΅ΠΌΠ΅ количСството Π΄Π°Π½Π½ΠΈ нараства, Π° ΠΏΠΎΡ‚Ρ€Π΅Π±ΠΈΡ‚Π΅Π»ΠΈΡ‚Π΅ ΠΎΡ‡Π°ΠΊΠ²Π°Ρ‚ Π½Π΅Π·Π°Π±Π°Π²Π½Π° рСакция ΠΎΡ‚ систСмитС. Π’ Ρ‚Π°ΠΊΠ°Π²Π° ситуация β€žΠΎΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΎΡ‚ΠΎβ€œ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ€Π°Π½Π΅, ΠΏΡ€ΠΈ ΠΊΠΎΠ΅Ρ‚ΠΎ ΠΈΠΌΠ°ΠΌΠ΅ Π΅Π΄ΠΈΠ½ ΠΈΠ·ΠΏΡŠΠ»Π½ΡΠ²Π°Ρ‰ ΠΏΠΎΡ‚ΠΎΠΊ, Π²Π΅Ρ‡Π΅ Π½Π΅ Π΅ Π΅Ρ„Π΅ΠΊΡ‚ΠΈΠ²Π½ΠΎ. НуТно Π΅ Π΄Π° Ρ€Π΅ΡˆΠΈΠΌ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° с Π΅Π΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΡ‚ΠΎ ΠΈΠ»ΠΈ ΠΊΠΎΠ½ΠΊΡƒΡ€Π΅Π½Ρ‚Π½ΠΎ изпълнСниС. ОсвСн Ρ‚ΠΎΠ²Π°, Ρ‚ΠΎΠ·ΠΈ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ ΡΡŠΡ‰Π΅ΡΡ‚Π²ΡƒΠ²Π° Π½Π° Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΈ Π½ΠΈΠ²Π°: Π½Π° Π½ΠΈΠ²ΠΎ ΠΏΠΎΡ‚ΠΎΡ†ΠΈ, Π½Π° Π½ΠΈΠ²ΠΎ процСси, Π½Π° Π½ΠΈΠ²ΠΎ машини Π² ΠΌΡ€Π΅ΠΆΠ°Ρ‚Π° (Ρ€Π°Π·ΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈ систСми). Π’ .NET ΠΈΠΌΠ° качСствСни, Π΄ΠΎΠΊΠ°Π·Π°Π»ΠΈ сС Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΠΈ Π·Π° Π±ΡŠΡ€Π·ΠΎ ΠΈ Π΅Ρ„Π΅ΠΊΡ‚ΠΈΠ²Π½ΠΎ Ρ€Π΅ΡˆΠ°Π²Π°Π½Π΅ Π½Π° Ρ‚Π°ΠΊΠΈΠ²Π° Π·Π°Π΄Π°Ρ‡ΠΈ.

Π—Π°Π΄Π°Ρ‡Π°

ЕдсгСр ДСйкстра Π΅ поставил Ρ‚ΠΎΠ·ΠΈ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ Π½Π° своитС студСнти ΠΎΡ‰Π΅ ΠΏΡ€Π΅Π· 1965 Π³ΠΎΠ΄ΠΈΠ½Π°. УстановСната Ρ„ΠΎΡ€ΠΌΡƒΠ»ΠΈΡ€ΠΎΠ²ΠΊΠ° Π΅ слСдната. Има ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΎ (ΠΎΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΎ ΠΏΠ΅Ρ‚) количСство философи ΠΈ ΡΡŠΡ‰ΠΎΡ‚ΠΎ количСство Π²ΠΈΠ»ΠΈΡ†ΠΈ. Π’Π΅ сСдят ΠΎΠΊΠΎΠ»ΠΎ ΠΊΡ€ΡŠΠ³Π»Π° маса, Π²ΠΈΠ»ΠΈΡ†ΠΈΡ‚Π΅ са ΠΌΠ΅ΠΆΠ΄Ρƒ тях. ЀилософитС ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° ядат ΠΎΡ‚ Ρ‡ΠΈΠ½ΠΈΠΈΡ‚Π΅ си, ΠΊΠΎΠΈΡ‚ΠΎ са пълни с Π±Π΅Π·ΠΊΡ€Π°ΠΉΠ½Π° Ρ…Ρ€Π°Π½Π°, Π΄Π° мислят ΠΈΠ»ΠΈ Π΄Π° Ρ‡Π°ΠΊΠ°Ρ‚. Π—Π° Π΄Π° ядС философ, трябва Π΄Π° Π²Π·Π΅ΠΌΠ΅ Π΄Π²Π΅ Π²ΠΈΠ»ΠΈΡ†ΠΈ (послСдният сподСля Π²ΠΈΠ»ΠΈΡ†Π° с ΠΏΡŠΡ€Π²ΠΈΡ). Π’Π·Π΅ΠΌΠ°Π½Π΅Ρ‚ΠΎ ΠΈ поставянСто Π½Π° Π²ΠΈΠ»ΠΈΡ†Π°Ρ‚Π° Π΅ Π΄Π²Π΅ ΠΎΡ‚Π΄Π΅Π»Π½ΠΈ дСйствия. Всички философи ΠΌΡŠΠ»Ρ‡Π°Ρ‚. Π—Π°Π΄Π°Ρ‡Π°Ρ‚Π° Π΅ Π΄Π° сС Π½Π°ΠΌΠ΅Ρ€ΠΈ Ρ‚Π°ΠΊΡŠΠ² Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΡŠΠΌ, Ρ‡Π΅ всички Ρ‚Π΅ Π΄Π° мислят ΠΈ Π΄Π° Π±ΡŠΠ΄Π°Ρ‚ сити, Π΄ΠΎΡ€ΠΈ слСд 54 Π³ΠΎΠ΄ΠΈΠ½ΠΈ.

ΠŸΡŠΡ€Π²ΠΎ Ρ‰Π΅ сС ΠΎΠΏΠΈΡ‚Π°ΠΌΠ΅ Π΄Π° Ρ€Π΅ΡˆΠΈΠΌ Ρ‚ΠΎΠ·ΠΈ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ Ρ‡Ρ€Π΅Π· ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° сподСлСно място. Π’ΠΈΠ»ΠΈΡ†ΠΈΡ‚Π΅ Π»Π΅ΠΆΠ°Ρ‚ Π½Π° ΠΎΠ±Ρ‰Π°Ρ‚Π° маса ΠΈ философитС просто Π³ΠΈ Π²Π·Π΅ΠΌΠ°Ρ‚, ΠΊΠΎΠ³Π°Ρ‚ΠΎ са Π½Π°Π»ΠΈΡ‡Π½ΠΈ, ΠΈ Π³ΠΈ поставят ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎ. Π’ΡƒΠΊ сС появяват ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠΈ със синхронизацията: ΠΊΠΎΠ³Π° Ρ‚ΠΎΡ‡Π½ΠΎ Π΄Π° сС Π²Π·ΠΈΠΌΠ°Ρ‚ Π²ΠΈΠ»ΠΈΡ†ΠΈΡ‚Π΅? ΠΊΠ°ΠΊΠ²ΠΎ Π΄Π° сС ΠΏΡ€Π°Π²ΠΈ, Π°ΠΊΠΎ Π²ΠΈΠ»ΠΈΡ†Π°Ρ‚Π° Π½Π΅ Π΅ Π½Π°Π»ΠΈΡ‡Π½Π°? ΠΈ Π΄Ρ€. Но ΠΏΡŠΡ€Π²ΠΎ Π½Π΅ΠΊΠ° Π΄Π° стартирамС философитС.

Π—Π° стартиранС Π½Π° ΠΏΠΎΡ‚ΠΎΡ†ΠΈΡ‚Π΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ ΠΏΡƒΠ» ΠΎΡ‚ ΠΏΠΎΡ‚ΠΎΡ†ΠΈ Ρ‡Ρ€Π΅Π· Task.Run ΠΌΠ΅Ρ‚ΠΎΠ΄:

var cancelTokenSource = new CancellationTokenSource();
Action create = (i) => RunPhilosopher(i, cancelTokenSource.Token);
for (int i = 0; i  create(icopy), cancelTokenSource.Token);
}

ΠŸΡƒΠ» ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²Π΅ Π΅ създадСн Π·Π° оптимизация Π½Π° ΡΡŠΠ·Π΄Π°Π²Π°Π½Π΅Ρ‚ΠΎ ΠΈ ΠΈΠ·Ρ‚Ρ€ΠΈΠ²Π°Π½Π΅Ρ‚ΠΎ Π½Π° ΠΏΠΎΡ‚ΠΎΡ†ΠΈ. Π’ΠΎΠ·ΠΈ ΠΏΡƒΠ» ΠΈΠΌΠ° опашка с Π·Π°Π΄Π°Ρ‡ΠΈ ΠΈ CLR създава ΠΈΠ»ΠΈ ΠΈΠ·Ρ‚Ρ€ΠΈΠ²Π° ΠΏΠΎΡ‚ΠΎΡ†ΠΈ Π² зависимост ΠΎΡ‚ броя Π½Π° Ρ‚Π΅Π·ΠΈ Π·Π°Π΄Π°Ρ‡ΠΈ. Π•Π΄ΠΈΠ½ ΠΏΡƒΠ» Π·Π° всички AppDomain-ΠΎΠ²Π΅. Π’ΠΎΠ·ΠΈ ΠΏΡƒΠ» трябва Π΄Π° сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° ΠΏΠΎΡ‡Ρ‚ΠΈ Π²ΠΈΠ½Π°Π³ΠΈ, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ Π½Π΅ Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π΄Π° сС Π·Π°Π½ΠΈΠΌΠ°Π²Π°Ρ‚Π΅ с ΡΡŠΠ·Π΄Π°Π²Π°Π½Π΅Ρ‚ΠΎ, ΠΈΠ·Ρ‚Ρ€ΠΈΠ²Π°Π½Π΅Ρ‚ΠΎ Π½Π° ΠΏΠΎΡ‚ΠΎΡ†ΠΈ ΠΈ Ρ‚Π΅Ρ…Π½ΠΈΡ‚Π΅ опашки ΠΈ Ρ‚.Π½. МоТС ΠΈ Π±Π΅Π· ΠΏΡƒΠ», Π½ΠΎ Ρ‚ΠΎΠ³Π°Π²Π° Ρ‰Π΅ трябва Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚Π΅ Π΄ΠΈΡ€Π΅ΠΊΡ‚Π½ΠΎ ΠŸΠΎΡ‚ΠΎΠΊ, Ρ‚ΠΎΠ²Π° Π΅ Ρ€Π°Π·ΡƒΠΌΠ½ΠΎ Π² случаи, ΠΊΠΎΠ³Π°Ρ‚ΠΎ трябва Π΄Π° ΠΏΡ€ΠΎΠΌΠ΅Π½ΠΈΡ‚Π΅ ΠΏΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚Π° Π½Π° ΠΏΠΎΡ‚ΠΎΠΊΠ°, ΠΊΠΎΠ³Π°Ρ‚ΠΎ ΠΈΠΌΠ°ΠΌΠ΅ дълга опСрация, Π·Π° Foreground ΠΏΠΎΡ‚ΠΎΠΊ ΠΈ Π΄Ρ€.

Π‘ Π΄Ρ€ΡƒΠ³ΠΈ Π΄ΡƒΠΌΠΈ, System.Threading.Tasks.Task ΠΊΠ»Π°ΡΡŠΡ‚ β€” Ρ‚ΠΎΠ²Π° Π΅ ΡΡŠΡ‰ΠΎΡ‚ΠΎ ΠŸΠΎΡ‚ΠΎΠΊ, Π½ΠΎ с всякакви удобства: Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ Π΄Π° стартиратС Π·Π°Π΄Π°Ρ‡Π° слСд Π±Π»ΠΎΠΊ ΠΎΡ‚ Π΄Ρ€ΡƒΠ³ΠΈ Π·Π°Π΄Π°Ρ‡ΠΈ, Π΄Π° Π³ΠΈ Π²Ρ€ΡŠΡ‰Π°Ρ‚Π΅ ΠΎΡ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, ΡƒΠ΄ΠΎΠ±Π½ΠΎ Π΄Π° Π³ΠΈ ΠΏΡ€Π΅ΠΊΡŠΡΠ²Π°Ρ‚Π΅ ΠΈ ΠΌΠ½. Π΄Ρ€. Π’Π΅ са Π½ΡƒΠΆΠ½ΠΈ Π·Π° ΠΏΠΎΠ΄Π΄Ρ€ΡŠΠΆΠΊΠ° Π½Π° async/await конструкции (Task-based Asynchronous Pattern, синтактичСн Π·Π°Ρ…Π°Ρ€ Π·Π° ΠΎΡ‡Π°ΠΊΠ²Π°Π½Π΅ Π½Π° 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();
    }
}

Π’ΡƒΠΊ ΠΏΡŠΡ€Π²ΠΎ ΠΎΠΏΠΈΡ‚Π²Π°ΠΌΠ΅ Π΄Π° Π²Π·Π΅ΠΌΠ΅ΠΌ лявата, Π° слСд Ρ‚ΠΎΠ²Π° ΠΈ дясната Π²ΠΈΠ»ΠΈΡ†Π° ΠΈ Π°ΠΊΠΎ успССм, ядСм ΠΈ Π³ΠΈ слагамС ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎ. Π’Π·Π΅ΠΌΠ°Π½Π΅Ρ‚ΠΎ Π½Π° Π΅Π΄Π½Π° Π²ΠΈΠ»ΠΈΡ†Π° Π΅ Π°Ρ‚ΠΎΠΌΠ°Ρ€Π½ΠΎ, Ρ‚.Π΅. Π΄Π²Π° ΠΏΠΎΡ‚ΠΎΠΊΠ° Π½Π΅ ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° Π²Π·Π΅ΠΌΠ°Ρ‚ Π΅Π΄Π½Π° ΠΈ ΡΡŠΡ‰Π° Π²ΠΈΠ»ΠΈΡ†Π° Π΅Π΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ (Π½Π΅ΠΏΡ€Π°Π²ΠΈΠ»Π½ΠΎ: ΠΏΡŠΡ€Π²ΠΈΡΡ‚ Ρ‡Π΅Ρ‚Π΅, Ρ‡Π΅ Π²ΠΈΠ»ΠΈΡ†Π°Ρ‚Π° Π΅ свободна, вторият β€” ΡΡŠΡ‰ΠΎ, ΠΏΡŠΡ€Π²ΠΈΡΡ‚ Π²Π·Π΅ΠΌΠ°, вторият Π²Π·Π΅ΠΌΠ°). Π—Π° Ρ‚ΠΎΠ²Π° Interlocked.CompareExchange, ΠΊΠΎΠΉΡ‚ΠΎ трябва Π΄Π° бъдС Ρ€Π΅Π°Π»ΠΈΠ·ΠΈΡ€Π°Π½ с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° процСсорна инструкция (TSL, XCHG), която Π±Π»ΠΎΠΊΠΈΡ€Π° участок ΠΏΠ°ΠΌΠ΅Ρ‚ Π·Π° Π°Ρ‚ΠΎΠΌΠ°Ρ€Π½ΠΎ послСдоватСлно Ρ‡Π΅Ρ‚Π΅Π½Π΅ ΠΈ запис. А SpinWait Π΅ Π΅ΠΊΠ²ΠΈΠ²Π°Π»Π΅Π½Ρ‚Π½ΠΎ Π½Π° конструкцията while(true) само с ΠΌΠ°Π»ΠΊΠ° «магия» β€” ΠΏΠΎΡ‚ΠΎΠΊΡŠΡ‚ Π·Π°Π΅ΠΌΠ° процСсора (Thread.SpinWait), Π½ΠΎ понякога ΠΏΡ€Π΅Π΄Π°Π²Π° ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅Ρ‚ΠΎ Π½Π° Π΄Ρ€ΡƒΠ³ ΠΏΠΎΡ‚ΠΎΠΊ (Thread.Yeild) ΠΈΠ»ΠΈ заспива (Thread.Sleep).

Но Ρ‚ΠΎΠ²Π° Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ Π½Π΅ Ρ€Π°Π±ΠΎΡ‚ΠΈ, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²Π΅Ρ‚Π΅ скоро (ΠΏΡ€ΠΈ ΠΌΠ΅Π½ Π² Ρ€Π°ΠΌΠΊΠΈΡ‚Π΅ Π½Π° сСкунда) сС Π±Π»ΠΎΠΊΠΈΡ€Π°Ρ‚: всички философи Π²Π·Π΅ΠΌΠ°Ρ‚ своята лява Π²ΠΈΠ»ΠΈΡ†Π°, Π° дСсната β€” Π½Π΅. ΠœΠ°ΡΡΠΈΠ²ΡŠΡ‚ forks Ρ‚ΠΎΠ³Π°Π²Π° ΠΈΠΌΠ° стойности: 1 2 3 4 5.

Π‘ΠΈΡ‚ΠΈΡ‚Π΅ философи ΠΈΠ»ΠΈ ΠΊΠΎΠ½ΠΊΡƒΡ€Π΅Π½Ρ‚Π½ΠΎ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ€Π°Π½Π΅ Π½Π° .NET

На схСмата, Π±Π»ΠΎΠΊΠΈΡ€Π°Π½Π΅Ρ‚ΠΎ Π½Π° ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ²Π΅Ρ‚Π΅ (deadlock). Π’ Π·Π΅Π»Π΅Π½ΠΎ β€” изпълнСниС, Π² Ρ‡Π΅Ρ€Π²Π΅Π½ΠΎ β€” синхронизация, Π² сиво β€” ΠΏΠΎΡ‚ΠΎΠΊ спи. Π ΠΎΠΌΠ±ΠΈΡ‚Π΅ ΠΎΠ±ΠΎΠ·Π½Π°Ρ‡Π°Π²Π°Ρ‚ Π²Ρ€Π΅ΠΌΠ΅Ρ‚ΠΎ Π·Π° стартиранС Π½Π° Task-ΠΎΠ²Π΅.

Π“Π»Π°Π΄ Π½Π° философитС

Π’ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‡Π΅ Π½Π΅ Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π΄Π° мислиш особСно ΠΌΠ½ΠΎΠ³ΠΎ, Π·Π° Π΄Π° сС Π½Π°Ρ…Ρ€Π°Π½ΠΈΡˆ, Π³Π»Π°Π΄ΡŠΡ‚ ΠΌΠΎΠΆΠ΅ Π΄Π° Π½Π°ΠΊΠ°Ρ€Π° всСки Π΄Π° Π·Π°Ρ€Π΅ΠΆΠ΅ философията. НСка ΠΎΠΏΠΈΡ‚Π°ΠΌΠ΅ Π΄Π° симулирамС ситуация Π½Π° Π³Π»Π°Π΄ Π½Π° нишки Π² Π½Π°ΡˆΠ°Ρ‚Π° Π·Π°Π΄Π°Ρ‡Π°. Π“Π»Π°Π΄ΡŠΡ‚ Π΅, ΠΊΠΎΠ³Π°Ρ‚ΠΎ Π½ΠΈΡˆΠΊΠ°Ρ‚Π° Ρ€Π°Π±ΠΎΡ‚ΠΈ, Π½ΠΎ Π±Π΅Π· ΡΡŠΡ‰Π΅ΡΡ‚Π²Π΅Π½Π° Ρ€Π°Π±ΠΎΡ‚Π°, с Π΄Ρ€ΡƒΠ³ΠΈ Π΄ΡƒΠΌΠΈ, Ρ‚ΠΎΠ²Π° Π΅ ΡΡŠΡ‰ΠΈΡΡ‚ Π΄Π΅Π΄Π»ΠΎΠΊ, просто сСга Π½ΠΈΡˆΠΊΠ°Ρ‚Π° Π½Π΅ спи, Π° Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎ Ρ‚ΡŠΡ€ΡΠΈ ΠΊΠ°ΠΊ Π΄Π° сС Π½Π°Ρ…Ρ€Π°Π½ΠΈ, Π½ΠΎ Ρ…Ρ€Π°Π½Π° няма. Π—Π° Π΄Π° ΠΈΠ·Π±Π΅Π³Π½Π΅ΠΌ чСсто Π±Π»ΠΎΠΊΠΈΡ€Π°Π½Π΅, Ρ‰Π΅ оставим Π²ΠΈΠ»ΠΈΡ†Π°Ρ‚Π° Π½Π°Π·Π°Π΄, Π°ΠΊΠΎ Π½Π΅ смС успСли Π΄Π° Π²Π·Π΅ΠΌΠ΅ΠΌ Π΄Ρ€ΡƒΠ³Π°.

// Π’ΠΎ ΠΆΠ΅ Ρ‡Ρ‚ΠΎ ΠΈ Π² 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)
    );
}

Π’ Ρ‚ΠΎΠ·ΠΈ ΠΊΠΎΠ΄ Π΅ Π²Π°ΠΆΠ½ΠΎ, Ρ‡Π΅ Π΄Π²Π°ΠΌΠ° ΠΎΡ‚ Ρ‡Π΅Ρ‚ΠΈΡ€ΠΈΠΌΠ° философи забравят Π΄Π° слоТат лявата си Π²ΠΈΠ»ΠΈΡ†Π°. И Π² ΠΊΡ€Π°ΠΉΠ½Π° смСтка Ρ‚Π΅ ядат ΠΏΠΎΠ²Π΅Ρ‡Π΅ Ρ…Ρ€Π°Π½Π°, Π° Π΄Ρ€ΡƒΠ³ΠΈΡ‚Π΅ Π·Π°ΠΏΠΎΡ‡Π²Π°Ρ‚ Π΄Π° Π³Π»Π°Π΄ΡƒΠ²Π°Ρ‚, Π²ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‡Π΅ Π½ΠΈΡˆΠΊΠΈΡ‚Π΅ ΠΈΠΌΠ°Ρ‚ Сднакъв ΠΏΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚. Π’ΡƒΠΊ Ρ‚Π΅ Π½Π΅ Π³Π»Π°Π΄ΡƒΠ²Π°Ρ‚ напълно, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ Π»ΠΎΡˆΠΈΡ‚Π΅ философи понякога оставят Π²ΠΈΠ»ΠΈΡ†ΠΈΡ‚Π΅ си Π½Π°Π·Π°Π΄. ИзглСТда, Ρ‡Π΅ Π΄ΠΎΠ±Ρ€ΠΈΡ‚Π΅ ядат ΠΎΠΊΠΎΠ»ΠΎ 5 ΠΏΡŠΡ‚ΠΈ ΠΏΠΎ-ΠΌΠ°Π»ΠΊΠΎ ΠΎΡ‚ Π»ΠΎΡˆΠΈΡ‚Π΅. Π’Π°ΠΊΠ° Ρ‡Π΅ ΠΌΠ°Π»ΠΊΠ° Π³Ρ€Π΅ΡˆΠΊΠ° Π² ΠΊΠΎΠ΄Π° Π²ΠΎΠ΄ΠΈ Π΄ΠΎ спад Π½Π° производитСлността. Π’ΡƒΠΊ Π΅ Π²Π°ΠΆΠ½ΠΎ Π΄Π° сС ΠΎΡ‚Π±Π΅Π»Π΅ΠΆΠΈ, Ρ‡Π΅ ΡΡŠΡ‰Π΅ΡΡ‚Π²ΡƒΠ²Π° рядка ситуация, ΠΊΠΎΠ³Π°Ρ‚ΠΎ всички философи Π²Π·Π΅ΠΌΠ°Ρ‚ лявата Π²ΠΈΠ»ΠΈΡ†Π°, дясната Π΅ Π½Π΅Π΄ΠΎΡΡ‚ΡŠΠΏΠ½Π°, Ρ‚Π΅ оставят лявата, Ρ‡Π°ΠΊΠ°Ρ‚, Π²Π·Π΅ΠΌΠ°Ρ‚ ΠΎΡ‚Π½ΠΎΠ²ΠΎ лявата ΠΈ Ρ‚.Π½. Π’Π°Π·ΠΈ ситуация ΡΡŠΡ‰ΠΎ Π΅ Π³Π»Π°Π΄, ΠΏΠΎ-скоро ΠΏΠΎΠ΄ΠΎΠ±Π½Π° Π½Π° Π²Π·Π°ΠΈΠΌΠ½Π° Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ°. НС успях Π΄Π° я повторя. По-Π΄ΠΎΠ»Ρƒ Π΅ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ Π½Π° ситуация, ΠΊΠΎΠ³Π°Ρ‚ΠΎ Π΄Π²Π°ΠΌΠ° лоши философи Π²Π·Π΅ΠΌΠ°Ρ‚ ΠΈ Π΄Π²Π΅Ρ‚Π΅ Π²ΠΈΠ»ΠΈΡ†ΠΈ, Π° Π΄Π²Π°ΠΌΠ° Π΄ΠΎΠ±Ρ€ΠΈ Π³Π»Π°Π΄ΡƒΠ²Π°Ρ‚.

Π‘ΠΈΡ‚ΠΈΡ‚Π΅ философи ΠΈΠ»ΠΈ ΠΊΠΎΠ½ΠΊΡƒΡ€Π΅Π½Ρ‚Π½ΠΎ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ€Π°Π½Π΅ Π½Π° .NET

Π’ΡƒΠΊ сС Π²ΠΈΠΆΠ΄Π°, Ρ‡Π΅ Π½ΠΈΡˆΠΊΠΈΡ‚Π΅ понякога сС ΡΡŠΠ±ΡƒΠΆΠ΄Π°Ρ‚ ΠΈ ΠΎΠΏΠΈΡ‚Π²Π°Ρ‚ Π΄Π° ΠΏΠΎΠ»ΡƒΡ‡Π°Ρ‚ рСсурс. Π”Π²Π° ΠΎΡ‚ Ρ‡Π΅Ρ‚ΠΈΡ€ΠΈ ядра Π½ΠΈΡ‰ΠΎ Π½Π΅ правят (зСлСният Π³Ρ€Π°Ρ„ΠΈΠΊ ΠΎΡ‚Π³ΠΎΡ€Π΅).

Π‘ΠΌΡŠΡ€Ρ‚ Π½Π° философа

И ΠΎΡ‰Π΅ Π΅Π΄Π½Π° ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ°, която ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΏΡ€Π΅ΠΊΡŠΡΠ½Π΅ славния обяд Π½Π° философитС β€” Π°ΠΊΠΎ Π΅Π΄ΠΈΠ½ ΠΎΡ‚ тях Π²Π½Π΅Π·Π°ΠΏΠ½ΠΎ ΡƒΠΌΡ€Π΅ с Π²ΠΈΠ»ΠΈΡ†ΠΈ Π² Ρ€ΡŠΡ†Π΅ (ΠΈ Π΄Π° бъдС ΠΏΠΎΠ³Ρ€Π΅Π±Π°Π½ Ρ‚Π°ΠΊΠ°). Π’ΠΎΠ³Π°Π²Π° ΡΡŠΡΠ΅Π΄ΠΈΡ‚Π΅ Ρ‰Π΅ останат Π±Π΅Π· обяд. ΠŸΡ€ΠΈΠΌΠ΅Ρ€ Π·Π° ΠΊΠΎΠ΄ Π·Π° Ρ‚ΠΎΠ·ΠΈ случай ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° измислитС сами, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ сС ΠΈΠ·ΠΊΠ»ΡŽΡ‡Π²Π° NullReferenceException слСд ΠΊΠ°Ρ‚ΠΎ Ρ„ΠΈΠ»ΠΎΡΠΎΡ„ΡŠΡ‚ Π²Π·Π΅ΠΌΠ΅ Π²ΠΈΠ»ΠΈΡ†ΠΈΡ‚Π΅. И, ΠΌΠ΅ΠΆΠ΄Ρƒ Π΄Ρ€ΡƒΠ³ΠΎΡ‚ΠΎ, ΠΈΠ·ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅Ρ‚ΠΎ няма Π΄Π° бъдС ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π΅Π½ΠΎ ΠΈ ΠΊΠΎΠ΄ΡŠΡ‚, ΠΊΠΎΠΉΡ‚ΠΎ Π³ΠΎ ΠΈΠ·Π²ΠΈΠΊΠ²Π°, просто няма Π΄Π° Π³ΠΎ ΡƒΠ»ΠΎΠ²ΠΈ (Π·Π° Ρ‚ΠΎΠ²Π° AppDomain.CurrentDomain.UnhandledException ΠΈ Π΄Ρ€.). Π‘Π»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»Π½ΠΎ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΡ†ΠΈΡ‚Π΅ Π½Π° Π³Ρ€Π΅ΡˆΠΊΠΈ са Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΈ Π² самитС нишки ΠΈ с ΠΊΠΎΡ€Π΅ΠΊΡ‚Π½ΠΎ ΠΏΡ€ΠΈΠΊΠ»ΡŽΡ‡Π²Π°Π½Π΅.

Π‘Π΅Ρ€Π²ΠΈΡ‚ΡŒΠΎΡ€

Π”ΠΎΠ±Ρ€Π΅, ΠΊΠ°ΠΊ Π΄Π° Ρ€Π΅ΡˆΠΈΠΌ Ρ‚ΠΎΠ·ΠΈ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ с Π²Π·Π°ΠΈΠΌΠ½ΠΈΡ‚Π΅ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ, Π³Π»Π°Π΄ΡƒΠ²Π°Π½Π΅Ρ‚ΠΎ ΠΈ ΡΠΌΡŠΡ€Ρ‚Π½ΠΈΡ‚Π΅ случаи? Π©Π΅ допускамС само Π΅Π΄ΠΈΠ½ философ Π΄ΠΎ Π²ΠΈΠ»ΠΈΡ†ΠΈΡ‚Π΅, Ρ‰Π΅ Π΄ΠΎΠ±Π°Π²ΠΈΠΌ Π²Π·Π°ΠΈΠΌΠ½ΠΎ ΠΈΠ·ΠΊΠ»ΡŽΡ‡Π²Π°Π½Π΅ Π·Π° Ρ‚ΠΎΠ²Π° място. Как Π΄Π° Π½Π°ΠΏΡ€Π°Π²ΠΈΠΌ Ρ‚ΠΎΠ·ΠΈ ΡΠ΅Ρ€Π²ΠΈΡ‚ΡŒΠΎΡ€ ΠΈ ΠΊΠ°ΠΊ философитС Ρ‰Π΅ ΠΌΡƒ искат, Π²ΡŠΠΏΡ€ΠΎΡΠΈΡ‚Π΅ са интСрСсни.

Най-простият Π½Π°Ρ‡ΠΈΠ½ Π΅ философитС просто постоянно Π΄Π° искат ΠΎΡ‚ ΡΠ΅Ρ€Π²ΠΈΡ‚ΡŒΠΎΡ€Π° Π΄Π° ΠΈΠΌ Ρ€Π°Π·Ρ€Π΅ΡˆΠΈ Π΄ΠΎΡΡ‚ΡŠΠΏ Π΄ΠΎ Π²ΠΈΠ»ΠΈΡ†ΠΈΡ‚Π΅. ВоСст, сСга философитС няма Π΄Π° Ρ‡Π°ΠΊΠ°Ρ‚ Π²ΠΈΠ»ΠΈΡ†Π°Ρ‚Π° Π΄Π° Π΅ Π½Π°Π±Π»ΠΈΠ·ΠΎ, Π° Ρ‰Π΅ Ρ‡Π°ΠΊΠ°Ρ‚ ΠΈΠ»ΠΈ Ρ‰Π΅ искат ΠΎΡ‚ ΡΠ΅Ρ€Π²ΠΈΡ‚ΡŒΠΎΡ€Π°. ΠŸΡŠΡ€Π²ΠΎΠ½Π°Ρ‡Π°Π»Π½ΠΎ Ρ‰Π΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ само потрСбитСлското пространство, Π² ΠΊΠΎΠ΅Ρ‚ΠΎ Π½Π΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ ΠΏΡ€Π΅ΠΊΡŠΡΠ²Π°Π½ΠΈΡ Π·Π° ΠΏΠΎΠ²ΠΈΠΊΠ²Π°Π½Π΅ Π½Π° някакви ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€ΠΈ ΠΎΡ‚ ядрото.

РСшСния Π² потрСбитСлското пространство

Π’ΡƒΠΊ Ρ‰Π΅ Π½Π°ΠΏΡ€Π°Π²ΠΈΠΌ ΡΡŠΡ‰ΠΎΡ‚ΠΎ, ΠΊΠΎΠ΅Ρ‚ΠΎ ΠΏΡ€Π΅Π΄ΠΈ смС ΠΏΡ€Π°Π²ΠΈΠ»ΠΈ с Π΅Π΄Π½Π° Π²ΠΈΠ»ΠΈΡ†Π° ΠΈ Π΄Π²Π°ΠΌΠ° философи, Ρ‰Π΅ сС Π²ΡŠΡ€Ρ‚ΠΈΠΌ Π² Ρ†ΠΈΠΊΡŠΠ» ΠΈ Ρ‰Π΅ Ρ‡Π°ΠΊΠ°ΠΌΠ΅. Но сСга Ρ‚ΠΎΠ²Π° Ρ‰Π΅ Π±ΡŠΠ΄Π°Ρ‚ всичкитС философи ΠΈ Ρ‰Π΅ ΠΈΠΌΠ° само Π΅Π΄Π½Π° Π²ΠΈΠ»ΠΈΡ†Π°, Ρ‚.Π΅. ΠΌΠΎΠΆΠ΅ Π΄Π° сС ΠΊΠ°ΠΆΠ΅, Ρ‡Π΅ Ρ‰Π΅ ядС само Ρ‚ΠΎΠ·ΠΈ философ, ΠΊΠΎΠΉΡ‚ΠΎ Π΅ Π²Π·Π΅Π» Ρ‚Π°Π·ΠΈ β€žΠ·Π»Π°Ρ‚Π½Π° Π²ΠΈΠ»ΠΈΡ†Π°β€œ ΠΎΡ‚ ΡΠ΅Ρ€Π²ΠΈΡ‚ΡŒΠΎΡ€Π°. Π—Π° Ρ‚ΠΎΠ²Π° Ρ‰Π΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ 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
        {
            // Π’ΡƒΠΊ ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΈΠΌΠ° само Π΅Π΄ΠΈΠ½ ΠΏΠΎΡ‚ΠΎΠΊ (Π²Π·Π°ΠΈΠΌΠ½ΠΎ ΠΈΠ·ΠΊΠ»ΡŽΡ‡Π²Π°Π½Π΅).
            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; }, Π½ΠΎ с ΠΎΡ‰Π΅ ΠΏΠΎ-голяма β€žΠΌΠ°Π³ΠΈΡβ€œ, ΠΎΡ‚ΠΊΠΎΠ»ΠΊΠΎΡ‚ΠΎ Π² SpinWait (ΠΊΠΎΠΈΡ‚ΠΎ Ρ‚Π°ΠΌ сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚). Π‘Π΅Π³Π° Ρ‚ΠΎΠΉ ΠΌΠΎΠΆΠ΅ Π΄Π° Π±Ρ€ΠΎΠΈ Ρ‡Π°ΠΊΠ°Ρ‰ΠΈ, Π»Π΅ΠΊΠΎ Π΄Π° Π³ΠΈ приспи ΠΈ ΠΌΠ½ΠΎΠ³ΠΎ Π΄Ρ€ΡƒΠ³ΠΈ Π½Π΅Ρ‰Π°. ΠšΠ°Ρ‚ΠΎ цяло, ΠΏΡ€Π°Π²ΠΈ всичко възмоТно Π·Π° оптимизация. Но трябва Π΄Π° ΠΏΠΎΠΌΠ½ΠΈΠΌ, Ρ‡Π΅ Ρ‚ΠΎΠ²Π° Π΅ всС ΠΏΠ°ΠΊ Π°ΠΊΡ‚ΠΈΠ²Π΅Π½ Ρ†ΠΈΠΊΡŠΠ», ΠΊΠΎΠΉΡ‚ΠΎ ΠΏΠΎΠ΅ΠΌΠ° рСсурси Π½Π° процСсора ΠΈ Π·Π°Π΄ΡŠΡ€ΠΆΠ° ΠΏΠΎΡ‚ΠΎΠΊ, ΠΊΠΎΠΉΡ‚ΠΎ ΠΌΠΎΠΆΠ΅ Π΄Π° Π΄ΠΎΠ²Π΅Π΄Π΅ Π΄ΠΎ Π³Π»Π°Π΄ (Priority Inversion problem), Π°ΠΊΠΎ Π΅Π΄ΠΈΠ½ ΠΎΡ‚ философитС станС ΠΏΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚Π΅Π½ ΠΏΡ€Π΅Π΄ Π΄Ρ€ΡƒΠ³ΠΈΡ‚Π΅, Π½ΠΎ Π½Π΅ Ρ€Π°Π·ΠΏΠΎΠ»Π°Π³Π° със Π·Π»Π°Ρ‚Π½Π°Ρ‚Π° Π²ΠΈΠ»ΠΈΡ†Π°. Π—Π°Ρ‚ΠΎΠ²Π° Π³ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ само Π·Π° ΠΌΠ½ΠΎΠ³ΠΎ, ΠΌΠ½ΠΎΠ³ΠΎ ΠΊΡ€Π°Ρ‚ΠΊΠΈ ΠΏΡ€ΠΎΠΌΠ΅Π½ΠΈ Π² ΠΎΠ±Ρ‰Π°Ρ‚Π° ΠΏΠ°ΠΌΠ΅Ρ‚, Π±Π΅Π· Π½ΠΈΠΊΠ°ΠΊΠ²ΠΈ външни извиквания, Π²Π»ΠΎΠΆΠ΅Π½ΠΈ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ ΠΈ Ρ‚.Π½. ΠΈΠ·Π½Π΅Π½Π°Π΄ΠΈ.

Π‘ΠΈΡ‚ΠΈΡ‚Π΅ философи ΠΈΠ»ΠΈ ΠΊΠΎΠ½ΠΊΡƒΡ€Π΅Π½Ρ‚Π½ΠΎ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ€Π°Π½Π΅ Π½Π° .NET

Π˜Π»ΡŽΡΡ‚Ρ€Π°Ρ†ΠΈΡ Π·Π° SpinLock. ΠŸΠΎΡ‚ΠΎΡ†ΠΈΡ‚Π΅ постоянно β€žΡΠ΅ Π±ΠΎΡ€ΡΡ‚β€œ Π·Π° Π·Π»Π°Ρ‚Π½Π°Ρ‚Π° Π²ΠΈΠ»ΠΈΡ†Π°. ΠΠ°ΡΡ‚ΡŠΠΏΠ²Π°Ρ‚ ΠΏΡ€ΠΎΠ²Π°Π»ΠΈ β€” Π² ΠΈΠ»ΡŽΡΡ‚Ρ€Π°Ρ†ΠΈΡΡ‚Π° Π΅ ΠΎΠ±ΠΎΠ·Π½Π°Ρ‡Π΅Π½Π°Ρ‚Π° област. Π―Π΄Ρ€ΠΎΡ‚ΠΎ Π½Π΅ сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° напълно: само ΠΎΠΊΠΎΠ»ΠΎ 2/3 ΠΎΡ‚ Ρ‚Π΅Π·ΠΈ Ρ‡Π΅Ρ‚ΠΈΡ€ΠΈ ΠΏΠΎΡ‚ΠΎΠΊΠ°.

Π”Ρ€ΡƒΠ³ΠΎ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ Ρ‚ΡƒΠΊ Π±ΠΈ Π±ΠΈΠ»ΠΎ Π΄Π° сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° само Interlocked.CompareExchange с Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎ ΠΈΠ·Ρ‡Π°ΠΊΠ²Π°Π½Π΅, ΠΊΠ°ΠΊΡ‚ΠΎ Π΅ ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΎ Π² ΠΊΠΎΠ΄Π° ΠΏΠΎ-Π³ΠΎΡ€Π΅ (Π² Π³Π»Π°Π΄Π½ΠΈΡ‚Π΅ философи), Π½ΠΎ Ρ‚ΠΎΠ²Π°, ΠΊΠ°ΠΊΡ‚ΠΎ Π²Π΅Ρ‡Π΅ бСшС спомСнато, Ρ‚Π΅ΠΎΡ€Π΅Ρ‚ΠΈΡ‡Π½ΠΎ ΠΌΠΎΠΆΠ΅ Π΄Π° Π΄ΠΎΠ²Π΅Π΄Π΅ Π΄ΠΎ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ°.

Π—Π° Interlocked трябва Π΄Π° сС ΠΊΠ°ΠΆΠ΅, Ρ‡Π΅ Ρ‚Π°ΠΌ Π½Π΅ само CompareExchange, Π½ΠΎ ΠΈ Π΄Ρ€ΡƒΠ³ΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΈ Π·Π° Π°Ρ‚ΠΎΠΌΠ°Ρ€Π½ΠΎ Ρ‡Π΅Ρ‚Π΅Π½Π΅ ΠΈ писанС. И Ρ‡Ρ€Π΅Π· ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ Π² случай, Ρ‡Π΅ Π΄Ρ€ΡƒΠ³ ΠΏΠΎΡ‚ΠΎΠΊ успСС Π΄Π° Π½Π°ΠΏΡ€Π°Π²ΠΈ своитС измСнСния (Ρ‡Π΅Ρ‚Π΅Π½Π΅ 1, Ρ‡Π΅Ρ‚Π΅Π½Π΅ 2, запис 2, запис 1 Π΅ лошо), Ρ‚ΠΎΠΉ ΠΌΠΎΠΆΠ΅ Π΄Π° сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Π·Π° слоТни ΠΏΡ€ΠΎΠΌΠ΅Π½ΠΈ Π½Π° Π΅Π΄Π½ΠΎ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ (Interlocked Anything шаблон).

РСшСния Π² Ρ€Π΅ΠΆΠΈΠΌ Π½Π° ядро

Π—Π° Π΄Π° ΠΈΠ·Π±Π΅Π³Π½Π΅ΠΌ Π·Π°Π³ΡƒΠ±Π°Ρ‚Π° Π½Π° рСсурси Π² Ρ†ΠΈΠΊΡŠΠ»Π°, Π΄Π° Π²ΠΈΠ΄ΠΈΠΌ ΠΊΠ°ΠΊ ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° Π±Π»ΠΎΠΊΠΈΡ€Π°ΠΌΠ΅ ΠΏΠΎΡ‚ΠΎΠΊΠ°. Π‘ Π΄Ρ€ΡƒΠ³ΠΈ Π΄ΡƒΠΌΠΈ, ΠΏΡ€ΠΎΠ΄ΡŠΠ»ΠΆΠ°Π²Π°ΠΉΠΊΠΈ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° Π½ΠΈ, Π΄Π° Π²ΠΈΠ΄ΠΈΠΌ ΠΊΠ°ΠΊ ΡΠ΅Ρ€Π²ΠΈΡ‚ΡŒΠΎΡ€ΡŠΡ‚ Ρ‰Π΅ приспи философа ΠΈ Ρ‰Π΅ Π³ΠΎ ΡΡŠΠ±ΡƒΠ΄ΠΈ само ΠΊΠΎΠ³Π°Ρ‚ΠΎ Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ. ΠŸΡŠΡ€Π²ΠΎ, Π½Π΅ΠΊΠ° Π΄Π° Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ ΠΊΠ°ΠΊ Π΄Π° Π³ΠΎ Π½Π°ΠΏΡ€Π°Π²ΠΈΠΌ ΠΏΡ€Π΅Π· Ρ€Π΅ΠΆΠΈΠΌΠ° Π½Π° ядро Π½Π° ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΎΠ½Π½Π°Ρ‚Π° систСма. Всички структури Ρ‚Π°ΠΌ чСсто сС ΠΎΠΊΠ°Π·Π²Π°Ρ‚ ΠΏΠΎ-Π±Π°Π²Π½ΠΈ ΠΎΡ‚ Ρ‚Π΅Π·ΠΈ Π² пространството Π½Π° потрСбитСля. По-Π±Π°Π²Π½ΠΈ Π² няколко ΠΏΡŠΡ‚ΠΈ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ AutoResetEvent ΠΌΠΎΠΆΠ΅ Π΄Π° бъдС 53 ΠΏΡŠΡ‚ΠΈ ΠΏΠΎ-Π±Π°Π²Π΅Π½ SpinLock [Π ΠΈΡ…Ρ‚Π΅Ρ€]. Но с тях ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° синхронизирамС процСси Π² цялата систСма, нСзависимо ΠΎΡ‚ ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅Ρ‚ΠΎ.

ΠžΡΠ½ΠΎΠ²Π½Π°Ρ‚Π° конструкция Ρ‚ΡƒΠΊ Π΅ сСмафор, ΠΏΡ€Π΅Π΄Π»ΠΎΠΆΠ΅Π½ ΠΎΡ‚ ДСйкстра ΠΏΡ€Π΅Π΄ΠΈ ΠΏΠΎΠ²Π΅Ρ‡Π΅ ΠΎΡ‚ ΠΏΠΎΠ»ΠΎΠ²ΠΈΠ½ Π²Π΅ΠΊ. Π‘Π΅ΠΌΠ°Ρ„ΠΎΡ€ΡŠΡ‚ Π΅, опростСно ΠΊΠ°Π·Π°Π½ΠΎ, ΠΏΠΎΠ»ΠΎΠΆΠΈΡ‚Π΅Π»Π½ΠΎ цяло число, управлявано ΠΎΡ‚ систСмата, ΠΈ Π΄Π²Π΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ Π²ΡŠΡ€Ρ…Ρƒ Π½Π΅Π³ΠΎ - ΡƒΠ²Π΅Π»ΠΈΡ‡Π°Π²Π°Π½Π΅ ΠΈ намаляванС. Ако Π½Π΅ ΠΌΠΎΠΆΠ΅ Π΄Π° сС Π½Π°ΠΌΠ°Π»ΠΈ Π΄ΠΎ Π½ΡƒΠ»Π°, Ρ‚ΠΎΠ³Π°Π²Π° извикващият ΠΏΠΎΡ‚ΠΎΠΊ сС Π±Π»ΠΎΠΊΠΈΡ€Π°. ΠšΠΎΠ³Π°Ρ‚ΠΎ числото сС ΡƒΠ²Π΅Π»ΠΈΡ‡Π°Π²Π° ΠΎΡ‚ някой Π΄Ρ€ΡƒΠ³ Π°ΠΊΡ‚ΠΈΠ²Π΅Π½ ΠΏΠΎΡ‚ΠΎΠΊ/процСс, Ρ‚ΠΎΠ³Π°Π²Π° ΠΏΠΎΡ‚ΠΎΠΊΡŠΡ‚ сС пропуска, Π° ΡΠ΅ΠΌΠ°Ρ„ΠΎΡ€ΡŠΡ‚ ΠΎΡ‚Π½ΠΎΠ²ΠΎ сС намалява с броя Π½Π° ΠΏΡ€Π΅ΠΌΠΈΠ½Π°Π»ΠΈΡ‚Π΅. МоТС Π΄Π° сС прСдстави ΠΊΠ°Ρ‚ΠΎ Π²Π»Π°ΠΊΠΎΠ²Π΅ Π² тясно място с сСмафор. .NET ΠΏΡ€Π΅Π΄Π»Π°Π³Π° няколко конструкции с ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ: AutoResetEvent, ManualResetEvent, Mutex ΠΈ сам Semaphore. Π©Π΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ AutoResetEvent, Ρ‚ΠΎΠ²Π° Π΅ Π½Π°ΠΉ-простата ΠΎΡ‚ Ρ‚Π΅Π·ΠΈ конструкции: само Π΄Π²Π΅ стойности 0 ΠΈ 1 (false, true). НСйният ΠΌΠ΅Ρ‚ΠΎΠ΄ WaitOne() Π±Π»ΠΎΠΊΠΈΡ€Π° извикващия ΠΏΠΎΡ‚ΠΎΠΊ, Π°ΠΊΠΎ стойността Π΅ Π±ΠΈΠ»Π° 0, Π° Π°ΠΊΠΎ Π΅ 1, ΠΏΠΎΠ½ΠΈΠΆΠ°Π²Π° я Π΄ΠΎ 0 ΠΈ Π³ΠΎ пропуска. ΠœΠ΅Ρ‚ΠΎΠ΄ΡŠΡ‚ Set() ΡƒΠ²Π΅Π»ΠΈΡ‡Π°Π²Π° Π΄ΠΎ 1 ΠΈ пропуска Π΅Π΄ΠΈΠ½ Ρ‡Π°ΠΊΠ°Ρ‰, ΠΊΠΎΠΉΡ‚ΠΎ ΠΎΡ‚Π½ΠΎΠ²ΠΎ я ΠΏΠΎΠ½ΠΈΠΆΠ°Π²Π° Π΄ΠΎ 0. ДСйства ΠΊΠ°Ρ‚ΠΎ натискащ ΠΊΠ°ΠΏΠ°ΠΊ Π² ΠΌΠ΅Ρ‚Ρ€ΠΎΡ‚ΠΎ.

НСка услоТним Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅Ρ‚ΠΎ ΠΈ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ° Π·Π° всСки философ, Π° Π½Π΅ Π·Π° всички навСднъТ. Π’.Π΅. сСга ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° ΠΈΠΌΠ° няколко философи Π΅Π΄Π½ΠΎΠ²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎ, Π° Π½Π΅ само Π΅Π΄ΠΈΠ½. Но ΠΎΡ‚Π½ΠΎΠ²ΠΎ Π±Π»ΠΎΠΊΠΈΡ€Π°ΠΌΠ΅ Π΄ΠΎΡΡ‚ΡŠΠΏΠ° Π΄ΠΎ масата, Π·Π° Π΄Π° ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° Π²Π·Π΅ΠΌΠ΅ΠΌ Π²ΠΈΠ»ΠΈΡ†ΠΈΡ‚Π΅ ΠΊΠΎΡ€Π΅ΠΊΡ‚Π½ΠΎ, избягвайки Π³ΠΎΠ½ΠΊΠΈ (race conditions).

// Для блокирования ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠ³ΠΎ философа.
// Π˜Π½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ΡΡ: 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();
}

Π—Π° Π΄Π° Ρ€Π°Π·Π±Π΅Ρ€Π΅ΠΌ ΠΊΠ°ΠΊΠ²ΠΎ става, Π½Π΅ΠΊΠ° Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ случая, ΠΊΠΎΠ³Π°Ρ‚ΠΎ Ρ„ΠΈΠ»ΠΎΡΠΎΡ„ΡŠΡ‚ Π½Π΅ успява Π΄Π° Π²Π·Π΅ΠΌΠ΅ Π²ΠΈΠ»ΠΈΡ†ΠΈΡ‚Π΅, Ρ‚ΠΎΠ³Π°Π²Π° дСйствията ΠΌΡƒ Ρ‰Π΅ Π±ΡŠΠ΄Π°Ρ‚ Ρ‚Π°ΠΊΠΈΠ²Π°. Π’ΠΎΠΉ Ρ‡Π°ΠΊΠ° Π΄ΠΎΡΡ‚ΡŠΠΏ Π΄ΠΎ масата. ΠŸΠΎΠ»ΡƒΡ‡Π°Π²Π° Π³ΠΎ ΠΈ ΠΎΠΏΠΈΡ‚Π²Π° Π΄Π° Π²Π·Π΅ΠΌΠ΅ Π²ΠΈΠ»ΠΈΡ†ΠΈΡ‚Π΅. НС успява. Π’ΠΎΠΉ освобоТдава Π΄ΠΎΡΡ‚ΡŠΠΏΠ° Π΄ΠΎ масата (Π²Π·Π°ΠΈΠΌΠ½ΠΎ ΠΈΠ·ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅). И ΠΏΡ€Π΅ΠΌΠΈΠ½Π°Π²Π° ΠΏΡ€Π΅Π· своя β€žΠ½Π°Ρ‚ΠΈΡΠΊΠ°Ρ‰ ΠΊΠ°ΠΏΠ°ΠΊβ€œ (AutoResetEvent) (Π² Π½Π°Ρ‡Π°Π»ΠΎΡ‚ΠΎ Ρ‚Π΅ са ΠΎΡ‚Π²ΠΎΡ€Π΅Π½ΠΈ). Попада ΠΎΡ‚Π½ΠΎΠ²ΠΎ Π² Ρ†ΠΈΠΊΡŠΠ», Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ няма Π²ΠΈΠ»ΠΈΡ†ΠΈ. ΠžΠΏΠΈΡ‚Π²Π° Π΄Π° Π³ΠΈ Π²Π·Π΅ΠΌΠ΅ ΠΈ спира ΠΏΡ€ΠΈ своя β€žΠ½Π°Ρ‚ΠΈΡΠΊΠ°Ρ‰ ΠΊΠ°ΠΏΠ°ΠΊβ€œ. Някой ΠΏΠΎ-ΡƒΡΠΏΠ΅ΡˆΠ΅Π½ съсСд отдясно ΠΈΠ»ΠΈ отляво, ΠΊΠΎΠΉΡ‚ΠΎ Π΅ Π·Π°Π²ΡŠΡ€ΡˆΠΈΠ» Π΄Π° ядС, освобоТдава нашия философ, β€žΠΎΡ‚Π²Π°Ρ€ΡΠΉΠΊΠΈ нСговия притискащ ΠΊΠ°ΠΏΠ°ΠΊβ€œ. ΠΠ°ΡˆΠΈΡΡ‚ философ ΠΏΡ€Π΅ΠΌΠΈΠ½Π°Π²Π° ΠΏΡ€Π΅Π· Π½Π΅Π³ΠΎ (ΠΈ Ρ‚ΠΎΠΉ сС затваря слСд Π½Π΅Π³ΠΎ) Π·Π° Π²Ρ‚ΠΎΡ€ΠΈ ΠΏΡŠΡ‚. ΠžΠΏΠΈΡ‚Π²Π° Π·Π° Ρ‚Ρ€Π΅Ρ‚ΠΈ ΠΏΡŠΡ‚ Π΄Π° Π²Π·Π΅ΠΌΠ΅ Π²ΠΈΠ»ΠΈΡ†ΠΈΡ‚Π΅. УспСшно. И ΠΏΡ€Π΅ΠΌΠΈΠ½Π°Π²Π° ΠΏΡ€Π΅Π· своя натискащ ΠΊΠ°ΠΏΠ°ΠΊ, Π·Π° Π΄Π° обядва.

ΠšΠΎΠ³Π°Ρ‚ΠΎ Π² Ρ‚Π°ΠΊΡŠΠ² ΠΊΠΎΠ΄ ΠΈΠΌΠ° случайни Π³Ρ€Π΅ΡˆΠΊΠΈ (Ρ‚Π΅ Π²ΠΈΠ½Π°Π³ΠΈ ΡΡŠΡ‰Π΅ΡΡ‚Π²ΡƒΠ²Π°Ρ‚), Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΊΠΎΠ³Π°Ρ‚ΠΎ Π½Π΅ΠΏΡ€Π°Π²ΠΈΠ»Π½ΠΎ Π΅ ΡƒΠΊΠ°Π·Π°Π½ съсСд ΠΈΠ»ΠΈ Π΅ създадСн Π΅Π΄ΠΈΠ½ ΠΈ ΡΡŠΡ‰ ΠΎΠ±Π΅ΠΊΡ‚ AutoResetEvent Π·Π° всички (Enumerable.Repeat), Ρ‚ΠΎΠ³Π°Π²Π° философитС Ρ‰Π΅ Ρ‡Π°ΠΊΠ°Ρ‚ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΡ†ΠΈΡ‚Π΅, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ Ρ‚ΡŠΡ€ΡΠ΅Π½Π΅Ρ‚ΠΎ Π½Π° Π³Ρ€Π΅ΡˆΠΊΠΈ Π² Ρ‚Π°ΠΊΡŠΠ² ΠΊΠΎΠ΄ Π΅ доста слоТно Π½Π°Ρ‡ΠΈΠ½Π°Π½ΠΈΠ΅. ΠžΡ‰Π΅ Π΅Π΄Π½Π° ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ с Ρ‚ΠΎΠ²Π° Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ Π΅, Ρ‡Π΅ Ρ‚ΠΎ Π½Π΅ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€Π°, Ρ‡Π΅ някой философ няма Π΄Π° Π·Π°ΠΏΠΎΡ‡Π½Π΅ Π΄Π° Π³Π»Π°Π΄ΡƒΠ²Π°.

Π₯ΠΈΠ±Ρ€ΠΈΠ΄Π½ΠΈ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ

Π Π°Π·Π³Π»Π΅Π΄Π°Ρ…ΠΌΠ΅ Π΄Π²Π° ΠΏΠΎΠ΄Ρ…ΠΎΠ΄Π° Π·Π° синхронизация, ΠΊΠΎΠ³Π°Ρ‚ΠΎ оставамС Π² Ρ€Π΅ΠΆΠΈΠΌ Π½Π° ΠΏΠΎΡ‚Ρ€Π΅Π±ΠΈΡ‚Π΅Π» ΠΈ Π²ΡŠΡ€Ρ‚ΠΈΠΌ Ρ†ΠΈΠΊΡŠΠ», ΠΈ ΠΊΠΎΠ³Π°Ρ‚ΠΎ Π±Π»ΠΎΠΊΠΈΡ€Π°ΠΌΠ΅ ΠΏΠΎΡ‚ΠΎΠΊΠ° ΠΏΡ€Π΅Π· ядрото. ΠŸΡŠΡ€Π²ΠΈΡΡ‚ ΠΌΠ΅Ρ‚ΠΎΠ΄ Π΅ Π΄ΠΎΠ±ΡŠΡ€ Π·Π° ΠΊΡ€Π°Ρ‚ΠΊΠΈ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ, Π° вторият - Π·Π° Π΄ΡŠΠ»Π³ΠΎΡ‚Ρ€Π°ΠΉΠ½ΠΈ. ЧСсто сС Π½Π°Π»Π°Π³Π° ΠΏΡŠΡ€Π²ΠΎ ΠΊΡ€Π°Ρ‚ΠΊΠΎ Π΄Π° ΠΈΠ·Ρ‡Π°ΠΊΠ²Π°ΠΌΠ΅ промяна Π½Π° ΠΏΡ€ΠΎΠΌΠ΅Π½Π»ΠΈΠ²Π° Π² Ρ†ΠΈΠΊΡŠΠ»Π°, Π° слСд Ρ‚ΠΎΠ²Π° Π΄Π° Π±Π»ΠΎΠΊΠΈΡ€Π°ΠΌΠ΅ ΠΏΠΎΡ‚ΠΎΠΊΠ°, ΠΊΠΎΠ³Π°Ρ‚ΠΎ ΠΎΡ‡Π°ΠΊΠ²Π°Π½Π΅Ρ‚ΠΎ Π΅ дълго. Π’ΠΎΠ·ΠΈ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ Π΅ Ρ€Π΅Π°Π»ΠΈΠ·ΠΈΡ€Π°Π½ Π² Ρ‚.Π½. Ρ…ΠΈΠ±Ρ€ΠΈΠ΄Π½ΠΈ конструкции. Π’ΡƒΠΊ ΠΈΠΌΠ°ΠΌΠ΅ ΡΡŠΡ‰ΠΈΡ‚Π΅ конструкции, ΠΊΠ°ΠΊΠ²ΠΈΡ‚ΠΎ бяха Π·Π° Ρ€Π΅ΠΆΠΈΠΌΠ° ядро, Π½ΠΎ сСга с Ρ†ΠΈΠΊΡŠΠ» Π² Ρ€Π΅ΠΆΠΈΠΌ Π½Π° ΠΏΠΎΡ‚Ρ€Π΅Π±ΠΈΡ‚Π΅Π»: SemaphorSlim, ManualResetEventSlim ΠΈ Π΄Ρ€. Най-популярната конструкция Ρ‚ΡƒΠΊ Π΅ ΠœΠΎΠ½ΠΈΡ‚ΠΎΡ€, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ Π² C# ΠΈΠΌΠ° извСстния Π½Π° всички lock синтаксис. ΠœΠΎΠ½ΠΈΡ‚ΠΎΡ€ Ρ‚ΠΎΠ²Π° Π΅ ΡΡŠΡ‰ΠΈΡΡ‚ сСмафор с максимална стойност 1 (ΠΌΡŽΡ‚Π΅ΠΊΡ), Π½ΠΎ с ΠΏΠΎΠ΄Π΄Ρ€ΡŠΠΆΠΊΠ° Π½Π° ΠΈΠ·Ρ‡Π°ΠΊΠ²Π°Π½Π΅ Π² Ρ†ΠΈΠΊΡŠΠ», рСкурсия, шаблон Π½Π° ΠΏΡ€ΠΎΠΌΠ΅Π½Π»ΠΈΠ²Π° Π·Π° условиС (Π·Π° Π½Π΅Π³ΠΎ ΠΏΠΎ-Π΄ΠΎΠ»Ρƒ) ΠΈ Π΄Ρ€. НСка Π΄Π° Ρ€Π°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ с Π½Π΅Π³ΠΎ.

// БпрячСм ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ для ΠœΠΎΠ½ΠΈΡ‚ΠΎΡ€Π° ΠΎΡ‚ всСх, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π±Π΅Π· Π΄Π΅Π΄Π»ΠΎΠΊΠΎΠ².
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);
    }
}

Π’ΡƒΠΊ ΠΎΡ‚Π½ΠΎΠ²ΠΎ Π±Π»ΠΎΠΊΠΈΡ€Π°ΠΌΠ΅ цялата маса Π·Π° Π΄ΠΎΡΡ‚ΡŠΠΏ Π΄ΠΎ Π²ΠΈΠ»ΠΈΡ†ΠΈΡ‚Π΅, Π½ΠΎ сСга ΠΎΡ‚ΠΊΠ»ΡŽΡ‡Π²Π°ΠΌΠ΅ всички ΠΏΠΎΡ‚ΠΎΡ†ΠΈ навСднъТ, Π° Π½Π΅ ΡΡŠΡΠ΅Π΄ΠΈΡ‚Π΅, ΠΊΠΎΠ³Π°Ρ‚ΠΎ някой Π·Π°Π²ΡŠΡ€ΡˆΠΈ Π΄Π° ядС. ВоСст, ΠΏΡŠΡ€Π²ΠΎ, някой ядС ΠΈ Π±Π»ΠΎΠΊΠΈΡ€Π° ΡΡŠΡΠ΅Π΄ΠΈΡ‚Π΅, Π° ΠΊΠΎΠ³Π°Ρ‚ΠΎ Ρ‚ΠΎΠ·ΠΈ някой Π·Π°Π²ΡŠΡ€ΡˆΠΈ, Π½ΠΎ иска Π²Π΅Π΄Π½Π°Π³Π° ΠΎΡ‚Π½ΠΎΠ²ΠΎ Π΄Π° ядС, Ρ‚ΠΎΠΉ Π²Π»ΠΈΠ·Π° Π² Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠ° ΠΈ Π±ΡƒΠ΄ΠΈ ΡΡŠΡΠ΅Π΄ΠΈΡ‚Π΅ си, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ Π²Ρ€Π΅ΠΌΠ΅Ρ‚ΠΎ ΠΌΡƒ Π·Π° ΠΈΠ·Ρ‡Π°ΠΊΠ²Π°Π½Π΅ Π΅ ΠΏΠΎ-ΠΌΠ°Π»ΠΊΠΎ.

Π’Π°ΠΊΠ° избягвамС задънСни ΡƒΠ»ΠΈΡ†ΠΈ ΠΈ Π³Π»Π°Π΄ΡƒΠ²Π°Π½Π΅ Π½Π° някой философ. ИзползвамС Ρ†ΠΈΠΊΡŠΠ» Π·Π° ΠΊΡ€Π°Ρ‚ΠΊΠΎ ΠΈΠ·Ρ‡Π°ΠΊΠ²Π°Π½Π΅ ΠΈ Π±Π»ΠΎΠΊΠΈΡ€Π°ΠΌΠ΅ ΠΏΠΎΡ‚ΠΎΠΊΠ° Π·Π° дълго. ΠžΡ‚ΠΊΠ»ΡŽΡ‡Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° всички навСднъТ Ρ€Π°Π±ΠΎΡ‚ΠΈ ΠΏΠΎ-Π±Π°Π²Π½ΠΎ, ΠΎΡ‚ΠΊΠΎΠ»ΠΊΠΎΡ‚ΠΎ Π°ΠΊΠΎ ΠΎΡ‚ΠΊΠ»ΡŽΡ‡Π²Π°ΠΌΠ΅ само съсСда, ΠΊΠ°ΠΊΡ‚ΠΎ Π² Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅Ρ‚ΠΎ с AutoResetEvent, Π½ΠΎ Ρ€Π°Π·Π»ΠΈΠΊΠ°Ρ‚Π° Π½Π΅ трябва Π΄Π° Π΅ голяма, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΡŠΡ‚ трябва Π΄Π° останС Π² Ρ€Π΅ΠΆΠΈΠΌ Π½Π° ΠΏΠΎΡ‚Ρ€Π΅Π±ΠΈΡ‚Π΅Π» ΠΏΡŠΡ€Π²ΠΎΠ½Π°Ρ‡Π°Π»Π½ΠΎ.

Π’ lock ΡΠΈΠ½Ρ‚Π°ΠΊΡΠΈΡΡŠΡ‚ носи нСприятни ΠΈΠ·Π½Π΅Π½Π°Π΄ΠΈ. ΠŸΡ€Π΅ΠΏΠΎΡ€ΡŠΡ‡Π²Π° сС Π΄Π° сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° ΠœΠΎΠ½ΠΈΡ‚ΠΎΡ€ Π΄ΠΈΡ€Π΅ΠΊΡ‚Π½ΠΎ [Π ΠΈΡ…Ρ‚Π΅Ρ€] [Π•Ρ€ΠΈΠΊ Π›ΠΈΠΏΠ΅Ρ€Ρ‚]. Π•Π΄Π½Π° ΠΎΡ‚ тях Π΅, Ρ‡Π΅ lock Π²ΠΈΠ½Π°Π³ΠΈ ΠΈΠ·Π»ΠΈΠ·Π° ΠΎΡ‚ ΠœΠΎΠ½ΠΈΡ‚ΠΎΡ€, Π΄ΠΎΡ€ΠΈ Π°ΠΊΠΎ Π΅ ΠΈΠΌΠ°Π»ΠΎ ΠΈΠ·ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅, ΠΈ Ρ‚ΠΎΠ³Π°Π²Π° Π΄Ρ€ΡƒΠ³ ΠΏΠΎΡ‚ΠΎΠΊ ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΏΡ€ΠΎΠΌΠ΅Π½ΠΈ ΡΡŠΡΡ‚ΠΎΡΠ½ΠΈΠ΅Ρ‚ΠΎ Π½Π° ΠΎΠ±Ρ‰Π°Ρ‚Π° ΠΏΠ°ΠΌΠ΅Ρ‚. Π’ Ρ‚Π°ΠΊΠΈΠ²Π° случаи ΠΏΠΎ-чСсто Π΅ ΠΏΠΎ-Π΄ΠΎΠ±Ρ€Π΅ Π΄Π° Π²Π»Π΅Π·Π΅Ρ‚Π΅ Π² задънСна ΡƒΠ»ΠΈΡ†Π° ΠΈΠ»ΠΈ ΠΏΠΎ някакъв бСзопасСн Π½Π°Ρ‡ΠΈΠ½ Π΄Π° Π·Π°Π²ΡŠΡ€ΡˆΠΈΡ‚Π΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π°. Π”Ρ€ΡƒΠ³Π° ΠΈΠ·Π½Π΅Π½Π°Π΄Π° Π΅, Ρ‡Π΅ Monitor ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Π±Π»ΠΎΠΊΠΎΠ²Π΅ Π·Π° синхронизация (SyncBlock), ΠΊΠΎΠΈΡ‚ΠΎ са Π½Π°Π»ΠΈΡ‡Π½ΠΈ във всички ΠΎΠ±Π΅ΠΊΡ‚ΠΈ. Π‘Π»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»Π½ΠΎ, Π°ΠΊΠΎ сС ΠΈΠ·Π±Π΅Ρ€Π΅ нСподходящ ΠΎΠ±Π΅ΠΊΡ‚, лСсно ΠΌΠΎΠΆΠ΅ Π΄Π° сС ΠΏΠΎΠ»ΡƒΡ‡ΠΈ задънСна ΡƒΠ»ΠΈΡ†Π° (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π°ΠΊΠΎ сС Π½Π°ΠΏΡ€Π°Π²ΠΈ Π»ΠΎΠΊ Π²ΡŠΡ€Ρ…Ρƒ ΠΈΠ½Ρ‚Π΅Ρ€Π½ΠΈΡ€Π°Π½Π° строка). Π’ΠΈΠ½Π°Π³ΠΈ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ скрит ΠΎΠ±Π΅ΠΊΡ‚ Π·Π° Ρ‚ΠΎΠ²Π°.

ΠŸΠ°Ρ‚Ρ‚Π΅Ρ€Π½ Condition Variable позволява ΠΏΠΎ-ΠΊΡ€Π°Ρ‚ΠΊΠΎ Π΄Π° Ρ€Π΅Π°Π»ΠΈΠ·ΠΈΡ€Π°ΠΌΠ΅ ΠΈΠ·Ρ‡Π°ΠΊΠ²Π°Π½Π΅ Π½Π° слоТни условия. Π’ .NET Ρ‚ΠΎΠΉ Π΅ нСпълСн, спорСд ΠΌΠ΅Π½, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ идСята Π΅ Π΄Π° ΠΈΠΌΠ° няколко опашки Π·Π° няколко ΠΏΡ€ΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈ (ΠΊΠ°ΠΊΡ‚ΠΎ Π² Posix Threads), Π° Π½Π΅ само Π½Π° Π΅Π΄ΠΈΠ½ Π»ΠΎΠΊ. Π’ΠΎΠ³Π°Π²Π° ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° създадСм опашки Π·Π° всички философи. Но Π΄ΠΎΡ€ΠΈ ΠΈ Π² Ρ‚ΠΎΠ·ΠΈ Π²ΠΈΠ΄ Ρ‚ΠΎΠΉ позволява Π΄Π° ΡΡŠΠΊΡ€Π°Ρ‚ΠΈΠΌ ΠΊΠΎΠ΄Π°.

Много философи ΠΈΠ»ΠΈ асинхронно / await

Π”ΠΎΠ±Ρ€Π΅, сСга ΠΌΠΎΠΆΠ΅ΠΌ Π΅Ρ„Π΅ΠΊΡ‚ΠΈΠ²Π½ΠΎ Π΄Π° Π±Π»ΠΎΠΊΠΈΡ€Π°ΠΌΠ΅ нишки. Но ΠΊΠ°ΠΊΠ²ΠΎ, Π°ΠΊΠΎ ΠΈΠΌΠ°ΠΌΠ΅ ΠΌΠ½ΠΎΠ³ΠΎ философи? 100? 10000? НапримСр, ΠΏΠΎΠ»ΡƒΡ‡Π°Π²Π°ΠΌΠ΅ 100000 заявки Π½Π° ΡƒΠ΅Π± ΡΡŠΡ€Π²ΡŠΡ€Π°. Π‘ΡŠΠ·Π΄Π°Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° нишка Π·Π° всяка заявка Ρ‰Π΅ бъдС Ρ€Π°Π·Ρ…ΠΎΠ΄Π½ΠΎ, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ Ρ‚ΠΎΠ»ΠΊΠΎΠ²Π° ΠΌΠ½ΠΎΠ³ΠΎ нишки няма Π΄Π° ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° сС ΠΈΠ·ΠΏΡŠΠ»Π½ΡΠ²Π°Ρ‚ ΠΏΠ°Ρ€Π°Π»Π΅Π»Π½ΠΎ. Π©Π΅ сС ΠΈΠ·ΠΏΡŠΠ»Π½ΡΠ²Π°Ρ‚ само Ρ‚ΠΎΠ»ΠΊΠΎΠ²Π°, ΠΊΠΎΠ»ΠΊΠΎΡ‚ΠΎ логичСски ядра (ΠΏΡ€ΠΈ ΠΌΠ΅Π½ са 4). А всички останали просто Ρ‰Π΅ ΠΎΡ‚Π½Π΅ΠΌΠ°Ρ‚ рСсурси. Π•Π΄Π½ΠΎ ΠΎΡ‚ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡΡ‚Π° Π½Π° Ρ‚ΠΎΠ·ΠΈ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ Π΅ ΠΏΠ°Ρ‚ΡŠΡ€Π½ΡŠΡ‚ async / await. Π˜Π΄Π΅ΡΡ‚Π° Π΅, Ρ‡Π΅ функцията Π½Π΅ Π·Π°Π΄ΡŠΡ€ΠΆΠ° нишка, Π°ΠΊΠΎ трябва Π΄Π° ΠΈΠ·Ρ‡Π°ΠΊΠ° Π½Π΅Ρ‰ΠΎ, Π·Π° Π΄Π° ΠΏΡ€ΠΎΠ΄ΡŠΠ»ΠΆΠΈ. А ΠΊΠΎΠ³Π°Ρ‚ΠΎ Ρ‚ΠΎΠ²Π° Π½Π΅Ρ‰ΠΎ сС случи, тя възобновява ΠΈΠ·ΠΏΡŠΠ»Π½Π΅Π½ΠΈΠ΅Ρ‚ΠΎ си (Π½ΠΎ Π½Π΅ Π·Π°Π΄ΡŠΠ»ΠΆΠΈΡ‚Π΅Π»Π½ΠΎ Π² ΡΡŠΡ‰Π°Ρ‚Π° нишка!). Π’ нашия случай, Ρ‰Π΅ ΠΈΠ·Ρ‡Π°ΠΊΠ°ΠΌΠ΅ Π²ΠΈΠ»ΠΈΡ†ΠΈΡ‚Π΅.

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();
}

ΠœΠ΅Ρ‚ΠΎΠ΄ΡŠΡ‚ с асинхронно / await сС трансформира Π² Ρ…ΠΈΡ‚ΡŠΡ€ ΠΊΡ€Π°Π΅Π½ Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚, ΠΊΠΎΠΉΡ‚ΠΎ Π²Π΅Π΄Π½Π°Π³Π° Π²Ρ€ΡŠΡ‰Π° Π²ΡŠΡ‚Ρ€Π΅ΡˆΠ½ΠΈΡ си Task. Π§Ρ€Π΅Π· Π½Π΅Π³ΠΎ ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΠΈΠ·Ρ‡Π°ΠΊΠ°ΠΌΠ΅ Π·Π°Π²ΡŠΡ€ΡˆΠ²Π°Π½Π΅Ρ‚ΠΎ Π½Π° ΠΌΠ΅Ρ‚ΠΎΠ΄Π°, Π΄Π° Π³ΠΎ ΠΎΡ‚ΠΌΠ΅Π½ΠΈΠΌ ΠΈ всичко останало, ΠΊΠΎΠ΅Ρ‚ΠΎ ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΠΏΡ€Π°Π²ΠΈΠΌ с Task. Π’ΡŠΡ‚Ρ€Π΅ Π² ΠΌΠ΅Ρ‚ΠΎΠ΄Π°, крайният Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΠΈΡ€Π° ΠΈΠ·ΠΏΡŠΠ»Π½Π΅Π½ΠΈΠ΅Ρ‚ΠΎ. Π‘ΡŠΡ‰Π½ΠΎΡΡ‚Ρ‚Π° Π΅, Ρ‡Π΅ Π°ΠΊΠΎ няма закъснСниС, ΠΈΠ·ΠΏΡŠΠ»Π½Π΅Π½ΠΈΠ΅Ρ‚ΠΎ Π΅ синхронно, Π° Π°ΠΊΠΎ ΠΈΠΌΠ°, Π½ΠΈΡˆΠΊΠ°Ρ‚Π° сС освобоТдава. Π—Π° ΠΏΠΎ-Π΄ΠΎΠ±Ρ€ΠΎ Ρ€Π°Π·Π±ΠΈΡ€Π°Π½Π΅ Π½Π° Ρ‚ΠΎΠ²Π°, Π΅ ΠΏΠΎ-Π΄ΠΎΠ±Ρ€Π΅ Π΄Π° ΠΏΠΎΠ³Π»Π΅Π΄Π½Π΅ΠΌ Ρ‚ΠΎΠ·ΠΈ ΠΊΡ€Π°Π΅Π½ Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚. МоТСм Π΄Π° създадСм Π²Π΅Ρ€ΠΈΠ³ΠΈ ΠΎΡ‚ Ρ‚Π΅Π·ΠΈ асинхронно / await ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΈ.

Π”Π° тСствамС. Π Π°Π±ΠΎΡ‚Π°Ρ‚Π° Π½Π° 100 философи Π½Π° машина с 4 логичСски ядра, 8 сСкунди. ΠŸΡ€Π΅Π΄Ρ…ΠΎΠ΄Π½ΠΎΡ‚ΠΎ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ с Monitor изпълнявашС само 4-Ρ‚Π΅ ΠΏΡŠΡ€Π²ΠΈ нишки, Π° останалитС Π½Π΅ сС ΠΈΠ·ΠΏΡŠΠ»Π½ΡΠ²Π°Ρ…Π° ΠΈΠ·ΠΎΠ±Ρ‰ΠΎ. Всяка ΠΎΡ‚ Ρ‚Π΅Π·ΠΈ 4 нишки Π΅ ΠΈΠΌΠ°Π»Π° закъснСниС ΠΎΠΊΠΎΠ»ΠΎ 2мс. А Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅Ρ‚ΠΎ с async / await изпълни всички 100, ΠΏΡ€ΠΈ срСдно ΠΈΠ·Ρ‡Π°ΠΊΠ²Π°Π½Π΅ ΠΎΡ‚ 6.8 сСкунди Π·Π° всяка. Π Π°Π·Π±ΠΈΡ€Π° сС, Π² Ρ€Π΅Π°Π»Π½ΠΈΡ‚Π΅ систСми закъснСниС ΠΎΡ‚ 6 сСкунди Π΅ Π½Π΅ΠΏΡ€ΠΈΠ΅ΠΌΠ»ΠΈΠ²ΠΎ ΠΈ Π΅ ΠΏΠΎ-Π΄ΠΎΠ±Ρ€Π΅ Π΄Π° Π½Π΅ сС ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π²Π°Ρ‚ Ρ‚ΠΎΠ»ΠΊΠΎΠ²Π° заявки ΠΏΠΎ Ρ‚ΠΎΠ·ΠΈ Π½Π°Ρ‡ΠΈΠ½. Π Π΅ΡˆΠ΅Π½ΠΈΠ΅Ρ‚ΠΎ с Monitor сС ΠΎΠΊΠ°Π·Π° напълно Π½Π΅ΡΡŠΠ²ΠΌΠ΅ΡΡ‚ΠΈΠΌΠΎ.

Π—Π°ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅

ΠšΠ°ΠΊΡ‚ΠΎ Π»ΠΈΡ‡ΠΈΠΌ ΠΎΡ‚ Ρ‚Π΅Π·ΠΈ ΠΌΠ°Π»ΠΊΠΈ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΈ, .NET ΠΏΠΎΠ΄Π΄ΡŠΡ€ΠΆΠ° ΠΌΠ½ΠΎΠ³ΠΎ конструкции Π·Π° синхронизация. НС Π²ΠΈΠ½Π°Π³ΠΈ, ΠΎΠ±Π°Ρ‡Π΅, Π΅ ΠΎΡ‡Π΅Π²ΠΈΠ΄Π½ΠΎ ΠΊΠ°ΠΊ Π΄Π° Π³ΠΈ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅. Надявам сС, Ρ‡Π΅ Ρ‚Π°Π·ΠΈ статия Π΅ Π±ΠΈΠ»Π° ΠΏΠΎΠ»Π΅Π·Π½Π°. Π‘Π΅Π³Π° Π·Π°Π²ΡŠΡ€ΡˆΠ²Π°ΠΌΠ΅, Π½ΠΎ ΠΈΠΌΠ° ΠΎΡ‰Π΅ ΠΌΠ½ΠΎΠ³ΠΎ интСрСсни Ρ‚Π΅ΠΌΠΈ, ΠΊΠ°Ρ‚ΠΎ ΠΊΠΎΠ»Π΅ΠΊΡ†ΠΈΠΈ с бСзопасСн Π΄ΠΎΡΡ‚ΡŠΠΏ ΠΎΡ‚ ΠΏΠΎΡ‚ΠΎΡ†ΠΈ, TPL Dataflow, Ρ€Π΅Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈΡ€Π°Π½Π΅, ΠΌΠΎΠ΄Π΅Π» Π½Π° софтуСрни Ρ‚Ρ€Π°Π½Π·Π°ΠΊΡ†ΠΈΠΈ ΠΈ Π΄Ρ€.

Π˜Π·Ρ‚ΠΎΡ‡Π½ΠΈΡ†ΠΈ

Π˜Π·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com

ΠšΡƒΠΏΠ΅Ρ‚Π΅ Π½Π°Π΄Π΅ΠΆΠ΄Π΅Π½ хостинг Π·Π° сайтовС със Π·Π°Ρ‰ΠΈΡ‚Π° ΠΎΡ‚ DDoS, VPS ΠΈ VDS ΡΡŠΡ€Π²ΡŠΡ€ΠΈ πŸ”₯ ΠšΡƒΠΏΠ΅Ρ‚Π΅ Π½Π°Π΄Π΅ΠΆΠ΄Π΅Π½ хостинг Π·Π° сайтовС със Π·Π°Ρ‰ΠΈΡ‚Π° ΠΎΡ‚ DDoS, VPS ΠΈ VDS ΡΡŠΡ€Π²ΡŠΡ€ΠΈ | ProHoster