ื’ืขื–ื•ื ื˜-ืคืืกื˜ืขื›ืขืจ ืคื™ืœืึธืกืึธืคืขืจืก ืึธื“ืขืจ ืงืึทืžืคึผืขื˜ื™ื˜ื™ื•ื• .ื ืขื˜ ืคึผืจืึธื’ืจืึทืžืžื™ื ื’

ื’ืขื–ื•ื ื˜-ืคืืกื˜ืขื›ืขืจ ืคื™ืœืึธืกืึธืคืขืจืก ืึธื“ืขืจ ืงืึทืžืคึผืขื˜ื™ื˜ื™ื•ื• .ื ืขื˜ ืคึผืจืึธื’ืจืึทืžืžื™ื ื’

ืœืึธืžื™ืจ ื–ืขืŸ ื•ื•ื™ ืงืึทื ืงืขืจืึทื ื˜ ืื•ืŸ ืคึผืึทืจืึทืœืขืœ ืคึผืจืึธื’ืจืึทืžืžื™ื ื’ ืึทืจื‘ืขื˜ ืื™ืŸ .ื ืขื˜, ื ื™ืฆืŸ ื“ื™ ืคื™ืœืึธืกืึธืคืขืจืก ื“ื™ื™ื ื™ื ื’ ืคึผืจืึธื‘ืœืขื ื•ื•ื™ ืึท ื‘ื™ื™ึทืฉืคึผื™ืœ. ื“ืขืจ ืคึผืœืึทืŸ ืื™ื– ื“ืึธืก, ืคึฟื•ืŸ ื“ื™ ืกื™ื ื’ืงืจืึทื ืึทื–ื™ื™ืฉืึทืŸ ืคื•ืŸ ืคึฟืขื“ืขื / ืคึผืจืึทืกืขืกืึทื–, ืฆื• ื“ืขืจ ืึทืงื˜ื™ืึธืจ ืžืึธื“ืขืœ (ืื™ืŸ ื“ื™ ืคืืœื’ืขื ื“ืข ืคึผืึทืจืฅ). ื“ืขืจ ืึทืจื˜ื™ืงืœ ืงืขืŸ ื–ื™ื™ืŸ ื ื•ืฆื™ืง ืคึฟืึทืจ ื“ืขืจ ืขืจืฉื˜ืขืจ ื‘ืึทืงืึทื ื˜ืขืจ ืึธื“ืขืจ ืฆื• ื“ืขืจืคืจื™ืฉืŸ ื“ื™ื™ืŸ ื•ื•ื™ืกืŸ.

ืคืืจื•ื•ืืก ื˜ืึธืŸ ืขืก ื‘ื™ื™ึท ืึทืœืข? ื˜ืจืึทื ื–ื™ืกื˜ืขืจื– ื“ืขืจื’ืจื™ื™ื›ืŸ ื–ื™ื™ืขืจ ืžื™ื ื™ืžื•ื ื’ืจื™ื™ืก, ืžืึธืจ ืก ื’ืขื–ืขืฅ ืจืขืกืฅ ืื•ื™ืฃ ื“ื™ ื‘ืึทื’ืจืขื ืขืฆื•ื ื’ ืคื•ืŸ ื“ื™ ื’ื™ื›ืงื™ื™ึทื˜ ืคื•ืŸ ืœื™ื›ื˜ ืื•ืŸ ื“ืขืจื™ื‘ืขืจ ืึท ืคืึทืจื’ืจืขืกืขืจืŸ ืื™ื– ื‘ืืžืขืจืงื˜ ืื™ืŸ ื“ื™ ื ื•ืžืขืจ, ืžืขืจ ื˜ืจืึทื ื–ื™ืกื˜ืขืจื– ืงืขื ืขืŸ ื–ื™ื™ืŸ ื’ืขืžืื›ื˜. ืื™ืŸ ื“ืขืจ ื–ืขืœื‘ื™ืงืขืจ ืฆื™ื™ื˜, ื“ื™ ืกื•ืžืข ืคื•ืŸ โ€‹โ€‹ื“ืึทื˜ืŸ ืื™ื– ื’ืจืึธื•ื™ื ื’, ืื•ืŸ ื“ื™ ื ื™ืฆืขืจืก ื“ืขืจื•ื•ืึทืจื˜ืŸ ืึท ื‘ืึทืœื“ื™ืง ืขื ื˜ืคืขืจ ืคื•ืŸ ื“ื™ ืกื™ืกื˜ืขืžืขืŸ. ืื™ืŸ ืึทื–ืึท ืึท ืกื™ื˜ื•ืึทืฆื™ืข, "ื ืึธืจืžืึทืœ" ืคึผืจืึธื’ืจืึทืžืžื™ื ื’, ื•ื•ืขืŸ ืžื™ืจ ื”ืึธื‘ืŸ ืื™ื™ืŸ ืขืงืกืึทืงื™ื•ื˜ื™ื ื’ ืคืึธื“ืขื, ืื™ื– ื ื™ื˜ ืžืขืจ ืขืคืขืงื˜ื™ื•ื•. ืื™ืจ ื“ืึทืจืคึฟืŸ ืฆื• ืขืคืขืก ืกืึธืœื•ื•ืข ื“ื™ ืคึผืจืึธื‘ืœืขื ืคื•ืŸ ืกื™ื™ืžืึทืœื˜ื™ื™ื ื™ืึทืก ืึธื“ืขืจ ืงืึทื ืงืขืจืึทื ื˜ ื“ื•ืจื›ืคื™ืจื•ื ื’. ื“ืขืจืฆื•, ื“ืขื ืคึผืจืึธื‘ืœืขื ื™ื’ื–ื™ืกืฅ ืื™ืŸ ืคืึทืจืฉื™ื“ืขื ืข ืœืขื•ื•ืขืœืก: ืื•ื™ืฃ ื“ืขืจ ืžื“ืจื’ื” ืคื•ืŸ ืคึฟืขื“ืขื, ืื™ืŸ ื“ืขืจ ืžื“ืจื’ื” ืคื•ืŸ ืคึผืจืึทืกืขืกืึทื–, ืื™ืŸ ื“ืขืจ ืžื“ืจื’ื” ืคื•ืŸ ืžืืฉื™ื ืขืŸ ืื™ืŸ ื“ื™ ื ืขืฅ (ื“ื™ ืคื•ื ืื ื“ืขืจื’ืขื˜ื™ื™ืœื˜ ืกื™ืกื˜ืขืžืขืŸ). .ื ืขื˜ ื”ืื˜ ื”ื•ื™ืš-ืงื•ื•ืึทืœื™ื˜ืขื˜, ืฆื™ื™ึทื˜-ื˜ืขืกื˜ืขื“ ื˜ืขืงื ืึทืœืึทื“ื–ืฉื™ื– ืคึฟืึทืจ ื’ืขืฉื•ื•ื™ื ื“ ืื•ืŸ ื™ืคื™ืฉืึทื ื˜ืœื™ ืกืึทืœื•ื•ื™ื ื’ ืึทื–ืึท ืคึผืจืึธื‘ืœืขืžืก.

ืึทืจื‘ืขื˜

Edsger Dijkstra ื”ืึธื˜ ื’ืขืฉื˜ืขืœื˜ ื“ืขื ืคึผืจืึธื‘ืœืขื ืฆื• ื–ื™ื™ื ืข ืกื˜ื•ื“ืขื ื˜ืŸ ืฉื•ื™ืŸ ืื™ืŸ 1965. ื“ื™ ื’ืขื’ืจื™ื ื“ืขื˜ ืคืึธืจืžื™ื•ืœื™ื™ืฉืึทืŸ ืื™ื– ื•ื•ื™ ื’ื™ื™ื˜. ืขืก ืื™ื– ืึท ื–ื™ื›ืขืจ (ื’ืขื•ื•ืขื ืœื™ืš ืคื™ื ืฃ) ื ื•ืžืขืจ ืคื•ืŸ ืคื™ืœืึธืกืึธืคืขืจืก ืื•ืŸ ื“ื™ ื–ืขืœื‘ืข ื ื•ืžืขืจ ืคื•ืŸ ืคืึธืจืงืก. ื–ื™ื™ ื–ื™ืฆืŸ ื‘ื™ื™ ืึท ืงืฒึทืœืขื›ื™ืงืŸ ื˜ื™ืฉ, ื’ืึธืคึผืœ ืฆื•ื•ื™ืฉืŸ ื–ื™ื™. ืคื™ืœืึธืกืึธืคืขืจืก ืงืขื ืขืŸ ืขืกืŸ ืคื•ืŸ ื–ื™ื™ืขืจ ืคึผืœืึทื˜ืขืก ืคื•ืŸ ืกืึธืฃ ืขืกื ื•ื•ืึทืจื’, ื˜ืจืึทื›ื˜ืŸ ืึธื“ืขืจ ื•ื•ืึทืจื˜ืŸ. ืฆื• ืขืกืŸ ืึท ืคื™ืœืึธืกืึธืฃ, ืื™ืจ ื“ืึทืจืคึฟืŸ ืฆื• ื ืขืžืขืŸ ืฆื•ื•ื™ื™ ืคืึธืจืงืก (ื“ื™ ืœืขืฆื˜ืข ืฉืึทืจืขืก ื“ื™ ื’ืึธืคึผืœ ืžื™ื˜ ื“ืขืจ ืขืจืฉื˜ืขืจ). ืงืœื™ื™ึทื‘ืŸ ื–ื™ืš ืื•ืŸ ืฉื˜ืขืœืŸ ืึทืจืึธืคึผ ืึท ื’ืึธืคึผืœ ื–ืขื ืขืŸ ืฆื•ื•ื™ื™ ื‘ืึทื–ื•ื ื“ืขืจ ืึทืงืฉืึทื ื–. ืืœืข ืคื™ืœืื–ืืคืขืŸ ืฉืฐืฒื’ืŸ. ื“ื™ ืึทืจื‘ืขื˜ ืื™ื– ืฆื• ื’ืขืคึฟื™ื ืขืŸ ืึทื–ืึท ืึท ืึทืœื’ืขืจื™ื“ืึทื ืึทื– ืึทืœืข ืคื•ืŸ โ€‹โ€‹ื–ื™ื™ ื•ื•ืึธืœื˜ ื˜ืจืึทื›ื˜ืŸ ืื•ืŸ ื–ื™ื™ืŸ ืคื•ืœ ืืคื™ืœื• ื ืึธืš 54 ื™ืืจ.

ืขืจืฉื˜ืขืจ, ืœืึธื–ืŸ ืก ืคึผืจื•ื‘ื™ืจืŸ ืฆื• ืกืึธืœื•ื•ืข ื“ืขื ืคึผืจืึธื‘ืœืขื ื“ื•ืจืš ื“ื™ ื ื•ืฆืŸ ืคื•ืŸ ืึท ืฉืขืจื“ ืคึผืœืึทืฅ. ื“ื™ ื’ืึธืคึผืœ ืœื™ื’ืŸ ืื•ื™ืฃ ื“ื™ ืคึผืจืึธืกื˜ ื˜ื™ืฉ ืื•ืŸ ื“ื™ ืคื™ืœืึธืกืึธืคืขืจืก ืคืฉื•ื˜ ื ืขืžืขืŸ ื–ื™ื™ ื•ื•ืขืŸ ื–ื™ื™ ื–ืขื ืขืŸ ืื•ืŸ ืฉื˜ืขืœืŸ ื–ื™ื™ ืฆื•ืจื™ืง. ื“ืึธ ืขืก ื–ืขื ืขืŸ ืคึผืจืึธื‘ืœืขืžืก ืžื™ื˜ ืกื™ื ื’ืงืจืึทื ืึทื–ื™ื™ืฉืึทืŸ, ื•ื•ืขืŸ ืคึผื•ื ืงื˜ ืฆื• ื ืขืžืขืŸ ื–ื™ื›ืขืจืขืขืฅ? ื•ื•ืึธืก ืื•ื™ื‘ ืขืก ืื™ื– ืงื™ื™ืŸ ื’ืึธืคึผืœ? ื•ื›ื•', ืื‘ืขืจ ืงื•ื“ื ืœืืžื™ืจ ืื ื”ื™ื™ื‘ืŸ ื“ื™ ืคื™ืœืืกืืคืŸ.

ืฆื• ืึธื ื”ื™ื™ื‘ืŸ ืคึฟืขื“ืขื, ืžื™ืจ ื ื•ืฆืŸ ืึท ืคืึธื“ืขื ื‘ืขืงืŸ ื“ื•ืจืš 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);
}

ื“ื™ ืคืึธื“ืขื ื‘ืขืงืŸ ืื™ื– ื“ื™ื–ื™ื™ื ื“ ืฆื• ืึทืคึผื˜ืึทืžื™ื™ื– ืคืึธื“ืขื ืฉืึทืคื•ื ื’ ืื•ืŸ ื“ื™ืœื™ืฉืึทืŸ. ื“ืขืจ ื‘ืขืงืŸ ื”ืื˜ ืึท ืจื™ื™ ืžื™ื˜ ื˜ืึทืกืงืก ืื•ืŸ ื“ื™ CLR ืงืจื™ื™ื™ืฅ ืึธื“ืขืจ ืจื™ืžื•ื•ื•ื– ืคึฟืขื“ืขื ื“ื™ืคึผืขื ื“ื™ื ื’ ืื•ื™ืฃ ื“ื™ ื ื•ืžืขืจ ืคื•ืŸ ื“ื™ ื˜ืึทืกืงืก. ืื™ื™ืŸ ื‘ืขืงืŸ ืคึฟืึทืจ ืึทืœืข ืึทืคึผืคึผื“ืึธืžืึทื™ื ืก. ื“ืขื ื‘ืขืงืŸ ื–ืึธืœ ื–ื™ื™ึทืŸ ื’ืขื ื™ืฆื˜ ื›ึผืžืขื˜ ืฉื˜ืขื ื“ื™ืง, ื•ื•ื™ื™ึทืœ. ื ื™ื˜ ื“ืึทืจืคึฟืŸ ืฆื• ืึทืจืŸ ืžื™ื˜ ืงืจื™ื™ื™ื˜ื™ื ื’, ื•ื™ืกืžืขืงืŸ ืคึฟืขื“ืขื, ื–ื™ื™ืขืจ ืงื™ื•ื–, ืืื–"ื• ื•. ืขืก ืื™ื– ืžืขื’ืœืขืš ืึธืŸ ืึท ื‘ืขืงืŸ, ืึธื‘ืขืจ ื“ืขืžืึธืœื˜ ืื™ืจ ื”ืึธื‘ืŸ ืฆื• ื ื•ืฆืŸ ืขืก ื’ืœื™ื™ึทืš Thread, ื“ืึธืก ืื™ื– ื ื•ืฆื™ืง ืคึฟืึทืจ ืงืึทืกืขืก ื•ื•ืขืŸ ืื™ืจ ื“ืึทืจืคึฟืŸ ืฆื• ื˜ื•ื™ืฉืŸ ื“ื™ ื‘ื™ืœื›ืขืจืงื™ื™ึทื˜ ืคื•ืŸ ืึท ืคืึธื“ืขื, ื•ื•ืขืŸ ืžื™ืจ ื”ืึธื‘ืŸ ืึท ืœืึทื ื’ ืึธืคึผืขืจืึทืฆื™ืข, ืคึฟืึทืจ ืึท ืคืึธืจื’ืจืึทื•ื ื“ ืคืึธื“ืขื, ืืื–"ื• ื•.

ืื™ืŸ ืื ื“ืขืจืข ื•ื•ืขืจื˜ืขืจ, System.Threading.Tasks.Task ืงืœืึทืก ืื™ื– ื“ื™ ื–ืขืœื‘ืข Thread, ืึธื‘ืขืจ ืžื™ื˜ ืึทืœืข ืกืึธืจืฅ ืคื•ืŸ ืงืึทื ื•ื•ื™ื ื™ืึทื ืกื™ื–: ื“ื™ ืคื™ื™ื™ืงื™ื™ื˜ ืฆื• ืœื•ื™ืคืŸ ืึท ืึทืจื‘ืขื˜ ื ืึธืš ืึท ื‘ืœืึธืง ืคื•ืŸ ืื ื“ืขืจืข ื˜ืึทืกืงืก, ืฆื•ืจื™ืงืงื•ืžืขืŸ ื–ื™ื™ ืคื•ืŸ ืคืึทื ื’ืงืฉืึทื ื–, ืงืึทื ื•ื•ื™ื ื™ืึทื ื˜ืœื™ ื™ื‘ืขืจืจื™ื™ึทืกืŸ ื–ื™ื™, ืื•ืŸ ืžืขืจ. ืขื˜ืง ื–ื™ื™ ื–ืขื ืขืŸ ื“ืืจืฃ ืฆื• ืฉื˜ื™ืฆืŸ ืึทืกื™ื ืง / ื“ืขืจื•ื•ืึทืจื˜ืŸ ืงืึทื ืกื˜ืจืึทืงืฉืึทื ื– (ื˜ืึทืกืง-ื‘ืื–ื™ืจื˜ ืึทืกื™ื ื˜ืฉืจืึธื ืึธื•ืก ืžื•ืกื˜ืขืจ, ืกื™ื ื˜ืึทืงื˜ื™ืง ืฆื•ืงืขืจ ืคึฟืึทืจ ื•ื•ืืจื˜ืŸ ืคึฟืึทืจ ื™ืึธ ืึทืคึผืขืจื™ื™ืฉืึทื ื–). ืžื™ืจ ื•ื•ืขืœืŸ ืจืขื“ืŸ ื•ื•ืขื’ืŸ ื“ืขื ืฉืคึผืขื˜ืขืจ.

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).

ืื‘ืขืจ ื“ืขื ืœื™ื™ื–ื•ื ื’ ื˜ื•ื˜ ื ื™ืฉื˜ ืึทืจื‘ืขื˜ืŸ, ื•ื•ื™ื™ึทืœ ื“ื™ ืฉื˜ืจืึธื ื–ืขื ืขืŸ ื‘ืึทืœื“ (ืคึฟืึทืจ ืžื™ืจ ืื™ืŸ ืึท ืจื’ืข) ืคืึทืจืฉืคึผืึทืจืŸ: ืึทืœืข ืคื™ืœืึธืกืึธืคืขืจืก ื ืขืžืขืŸ ื–ื™ื™ืขืจ ืœื™ื ืงืก ื’ืึธืคึผืœ, ืึธื‘ืขืจ ื ื™ืฉื˜ ื“ื™ ืจืขื›ื˜. ื“ื™ ืคืึธืจืงืก ืžืขื ื’ืข ื“ืขืžืึธืœื˜ ื”ืื˜ ื“ื™ ื•ื•ืึทืœื•ืขืก: 1 2 3 4 5.

ื’ืขื–ื•ื ื˜-ืคืืกื˜ืขื›ืขืจ ืคื™ืœืึธืกืึธืคืขืจืก ืึธื“ืขืจ ืงืึทืžืคึผืขื˜ื™ื˜ื™ื•ื• .ื ืขื˜ ืคึผืจืึธื’ืจืึทืžืžื™ื ื’

ืื™ืŸ ื“ื™ ืคื™ื’ื•ืจ, ื‘ืœืึทืงื™ื ื’ ืคึฟืขื“ืขื (ื“ืึทื“ืœืึทืง). ื’ืจื™ืŸ - ื“ื•ืจื›ืคื™ืจื•ื ื’, ืจื•ื™ื˜ - ืกื™ื ื’ืงืจืึทื ืึทื–ื™ื™ืฉืึทืŸ, ื’ืจื•ื™ - ื“ื™ ืคืึธื“ืขื ืื™ื– ืกืœื™ืคึผื™ื ื’. ื“ื™ ืจื”ืึธืžื‘ื•ืกืขืก ืึธื ื•ื•ื™ื™ึทื–ืŸ ื“ื™ ืึธื ื”ื™ื™ื‘ ืฆื™ื™ื˜ ืคื•ืŸ ื˜ืึทืกืงืก.

ื“ืขืจ ื”ื•ื ื’ืขืจ ืคื•ืŸ ื“ื™ ืคื™ืœืึธืกืึธืคืขืŸ

ื›ืึธื˜ืฉ ืขืก ืื™ื– ื ื™ื˜ ื ื™ื™ื˜ื™ืง ืฆื• ื˜ืจืึทื›ื˜ืŸ ืกืคึผืขืฆื™ืขืœ ืคื™ืœ ืขืกื ื•ื•ืึทืจื’, ืึธื‘ืขืจ ื”ื•ื ื’ืขืจ ืžืื›ื˜ ื•ื•ืขืจ ืขืก ื™ื– ื’ืขื‘ืŸ ืึทืจื•ื™ืฃ ืคื™ืœืึธืกืึธืคื™ืข. ื–ืืœ ืก ืคึผืจื•ื‘ื™ืจืŸ ืฆื• ืกื™ืžื•ืœื™ืจืŸ ื“ื™ ืกื™ื˜ื•ืึทืฆื™ืข ืคื•ืŸ โ€‹โ€‹ื”ื•ื ื’ืขืจ ืคื•ืŸ ืคึฟืขื“ืขื ืื™ืŸ ืื•ื ื“ื–ืขืจ ืคึผืจืึธื‘ืœืขื. ื”ื•ื ื’ืขืจ ืื™ื– ื•ื•ืขืŸ ื ืคืึธื“ืขื ืœื•ื™ืคื˜, ืึธื‘ืขืจ ืึธืŸ ื‘ืึทื˜ื™ื™ื˜ื™ืง ืึทืจื‘ืขื˜, ืื™ืŸ ืื ื“ืขืจืข ื•ื•ืขืจื˜ืขืจ, ื“ืึธืก ืื™ื– ื“ืขืจ ื–ืขืœื‘ื™ืงืขืจ ื“ืขื“ืœืึทืง, ื ืึธืจ ืื™ืฆื˜ ื“ื™ ืคืึธื“ืขื ืื™ื– ื ื™ืฉื˜ ืกืœื™ืคึผื™ื ื’, ืึธื‘ืขืจ ืื™ื– ืึทืงื˜ื™ื•ื•ืœื™ ืงื•ืงืŸ ืคึฟืึทืจ ืขืคึผืขืก ืฆื• ืขืกืŸ, ืึธื‘ืขืจ ืขืก ืื™ื– ืงื™ื™ืŸ ืขืกื ื•ื•ืึทืจื’. ืื™ืŸ ืกื“ืจ ืฆื• ื•ื™ืกืžื™ื™ื“ืŸ ืึธืคื˜ ื‘ืœืึทืงื™ื ื’, ืžื™ืจ ื•ื•ืขืœืŸ ืฉื˜ืขืœืŸ ื“ื™ ื’ืึธืคึผืœ ืฆื•ืจื™ืง ืื•ื™ื‘ ืžื™ืจ ืงืขืŸ ื ื™ืฉื˜ ื ืขืžืขืŸ ืืŸ ืื ื“ืขืจ ืื™ื™ื ืขืจ.

// ะขะพ ะถะต ั‡ั‚ะพ ะธ ะฒ 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 ืžืืœ ื•ื•ื™ื™ื ื™ืงืขืจ ื•ื•ื™ ืฉืœืขื›ื˜. ืึทื–ื•ื™ ืึท ืงืœื™ื™ืŸ ื˜ืขื•ืช ืื™ืŸ ื“ื™ ืงืึธื“ ืคื™ืจื˜ ืฆื• ืึท ืงืึทืคึผ ืื™ืŸ ืคืึธืจืฉื˜ืขืœื•ื ื’. ืขืก ืื™ื– ืื•ื™ืš ื›ื“ืื™ ืฆื• ื‘ืืžืขืจืงืŸ ื“ืึธ ืึทื– ืึท ื–ืขืœื˜ืŸ ืกื™ื˜ื•ืึทืฆื™ืข ืื™ื– ืžืขื’ืœืขืš ื•ื•ืขืŸ ืึทืœืข ืคื™ืœืึธืกืึธืคืขืจืก ื ืขืžืขืŸ ื“ื™ ืœื™ื ืงืก ื’ืึธืคึผืœ, ืขืก ืื™ื– ืงื™ื™ืŸ ืจืขื›ื˜ ืื™ื™ื ืขืจ, ื–ื™ื™ ืฉื˜ืขืœืŸ ื“ื™ ืœื™ื ืงืก, ื•ื•ืึทืจื˜ืŸ, ื ืขืžืขืŸ ื“ื™ ืœื™ื ืงืก ื•ื•ื™ื“ืขืจ, ืืื–"ื• ื•. ื“ื™ ืกื™ื˜ื•ืึทืฆื™ืข ืื™ื– ืื•ื™ืš ืึท ื”ื•ื ื’ืขืจ, ืžืขืจ ื•ื•ื™ ืึท ื“ืขื“ืœืึทืง. ืื™ืš ื”ืึธื‘ ื ื™ื˜ ื’ืขืงืขื ื˜ ืื™ื‘ืขืจื—ื–ืจืŸ. ื•ื ื˜ืขืจ ืื™ื– ืึท ื‘ื™ืœื“ ืคึฟืึทืจ ืึท ืกื™ื˜ื•ืึทืฆื™ืข ื•ื•ื• ืฆื•ื•ื™ื™ ืฉืœืขื›ื˜ ืคื™ืœืึธืกืึธืคืขืจืก ื”ืึธื‘ืŸ ื’ืขื ื•ืžืขืŸ ื‘ื™ื™ื“ืข ืคืึธืจืงืก ืื•ืŸ ืฆื•ื•ื™ื™ ื’ื•ื˜ืข ื–ืขื ืขืŸ ื”ื•ื ื’ืขืจื™ืง.

ื’ืขื–ื•ื ื˜-ืคืืกื˜ืขื›ืขืจ ืคื™ืœืึธืกืึธืคืขืจืก ืึธื“ืขืจ ืงืึทืžืคึผืขื˜ื™ื˜ื™ื•ื• .ื ืขื˜ ืคึผืจืึธื’ืจืึทืžืžื™ื ื’

ื“ืึธ ืื™ืจ ืงืขื ืขืŸ ื–ืขืŸ ืึทื– ื“ื™ ืคึฟืขื“ืขื ื•ื•ืขืงืŸ ื–ื™ืš ืžืืœ ืื•ืŸ ืคึผืจื•ื‘ื™ืจืŸ ืฆื• ื‘ืึทืงื•ืžืขืŸ ื“ื™ ืžื™ื˜ืœ. ืฆื•ื•ื™ื™ ืคื•ืŸ ื“ื™ ืคื™ืจ ืงืึธืจืขืก ื˜ืึธืŸ ื’ืึธืจื ื™ืฉื˜ (ื’ืจื™ืŸ ื’ืจืึทืคื™ืง ืื•ื™ื‘ืŸ).

ื˜ื•ื™ื˜ ืคื•ืŸ ืึท ืคื™ืœืึธืกืึธืฃ

ื ื•, ื ืืš ื ืคืจืื‘ืœืขื, ื•ื•ืืก ืงืขืŸ ืื™ื‘ืขืจื”ืขืจืŸ ื ื”ืขืจืœื™ื›ืข ื“ื™ื ืขืจ ืคื•ืŸ ืคื™ืœืื–ืืคืขืŸ, ืื™ื– ืื•ื™ื‘ ืื™ื™ื ืขืจ ืคื•ืŸ ื–ื™ื™ ืฉื˜ืขืจื˜ ืžื™ื˜ืืžืืœ ืžื™ื˜ ื’ืึธืคืœ ืื™ืŸ ื“ื™ ื”ืขื ื˜ (ืื•ืŸ ื–ื™ื™ ื•ื•ืขืœืŸ ืื™ื ืื–ื•ื™ ื‘ืึทื’ืจืึธื‘ืŸ). ื“ื ืŸ ืฐืขืœ ืŸ ื“ ื™ ืฉื›ื ื™ ื ื’ืขื‘ืœื™ื‘ ืŸ ื ืŸ ืžื™ื˜ืื’ . ืื™ืจ ืงืขื ืขืŸ ืงื•ืžืขืŸ ืึทืจื•ื™ืฃ ืžื™ื˜ ืึท ื‘ื™ื™ึทืฉืคึผื™ืœ ืงืึธื“ ืคึฟืึทืจ ื“ืขื ืคืึทืœ ื–ื™ืš, ืคึฟืึทืจ ื‘ื™ื™ึทืฉืคึผื™ืœ, ืขืก ืื™ื– ืืจืœื ื’ืขื•ื•ืืจืคืŸ NullReferenceException ื ืึธืš ื“ืขืจ ืคื™ืœืึธืกืึธืฃ ื ืขืžื˜ ื“ื™ ืคืึธืจืงืก. ืื•ืŸ, ื“ื•ืจืš ื“ืขื ื•ื•ืขื’, ื“ื™ ื•ื™ืกื ืขื ื•ื•ืขื˜ ื ื™ืฉื˜ ื–ื™ื™ืŸ ื›ืึทื ื“ืึทืœื“ ืื•ืŸ ื“ื™ ืคืึทืš ืงืึธื“ ื•ื•ืขื˜ ื ื™ืฉื˜ ื ืึธืจ ื›ืึทืคึผืŸ ืขืก (ืคึฟืึทืจ ื“ืขื AppDomain.CurrentDomain.UnhandledException ืื•ืŸ ื•ื›ื•'). ื“ืขืจื™ื‘ืขืจ, ื˜ืขื•ืช ื”ืึทื ื“ืœืขืจืก ื–ืขื ืขืŸ ื“ืืจืฃ ืื™ืŸ ื“ื™ ืคึฟืขื“ืขื ื–ื™ืš ืื•ืŸ ืžื™ื˜ ื’ืจืึทืฆื™ืขื– ื˜ืขืจืžืึทื ื™ื™ืฉืึทืŸ.

ืงืขืœื ืขืจ

ืึธื•ืงื™ื™, ื•ื•ื™ ื˜ืึธืŸ ืžื™ืจ ืกืึธืœื•ื•ืข ื“ืขื ื“ืขื“ืœืึทืง, ื”ื•ื ื’ืขืจ ืื•ืŸ ื˜ื•ื™ื˜ ืคึผืจืึธื‘ืœืขื? ืžื™ืจ ื•ื•ืขืœืŸ ืœืึธื–ืŸ ื‘ืœื•ื™ื– ืื™ื™ืŸ ืคื™ืœืึธืกืึธืฃ ืฆื• ื“ืขืจื’ืจื™ื™ื›ืŸ ื“ื™ ืคืึธืจืงืก, ืœื™ื™ื’ืŸ ืึท ืงืขื’ื ืฆื™ื™ึทื˜ื™ืง ื™ืงืกืงืœื•ื–ืฉืึทืŸ ืคื•ืŸ ืคึฟืขื“ืขื ืคึฟืึทืจ ื“ืขื ืึธืจื˜. ื•ื•ื™ ืฆื• ื˜ืึธืŸ ืขืก? ืจืขื›ืŸ ืขืก ืื™ื– ื“ื ื ืงืขืœื ืขืจ ืœืขื‘ืŸ ื“ื™ ืคื™ืœืืกืืคืŸ, ื•ื•ืืก ื’ื™ื˜ ืจืฉื•ืช ืคืืจ ื™ืขื“ืŸ ืื™ื™ื ืขื ืคื™ืœืื–ืืฃ ืฆื• ื ืขืžืขืŸ ื“ื™ ื’ืืคืœืŸ. ื•ื•ื™ ื˜ืึธืŸ ืžื™ืจ ืžืึทื›ืŸ ื“ืขื ืงืขืœื ืขืจ ืื•ืŸ ื•ื•ื™ ืคื™ืœืึธืกืึธืคืขืจืก ื•ื•ืขืœืŸ ืคืจืขื’ืŸ ืื™ื, ื“ื™ ืฉืืœื•ืช ื–ืขื ืขืŸ ื˜ืฉื™ืงืึทื•ื•ืข.

ื“ืขืจ ืกื™ืžืคึผืœืึทืกื˜ ื•ื•ืขื’ ืื™ื– ื•ื•ืขืŸ ื“ื™ ืคื™ืœืึธืกืึธืคืขืจืก ื•ื•ืขืœืŸ ืคืฉื•ื˜ ืงืขืกื™ื™ื“ืขืจ ืคืจืขื’ืŸ ื“ืขื ืงืขืœื ืขืจ ืคึฟืึทืจ ืฆื•ื˜ืจื™ื˜ ืฆื• ื“ื™ ืคืึธืจืงืก. ื™ืขื ืข. ืื™ืฆื˜ ืคื™ืœืึธืกืึธืคืขืจืก ื•ื•ืขืœืŸ ื ื™ืฉื˜ ื•ื•ืึทืจื˜ืŸ ืคึฟืึทืจ ืึท ื’ืึธืคึผืœ ื ื™ืจื‘ื™ื™, ืึธื‘ืขืจ ื•ื•ืึทืจื˜ืŸ ืึธื“ืขืจ ืคืจืขื’ืŸ ื“ื™ ืงืขืœื ืขืจ. ืื™ืŸ ืขืจืฉื˜ืขืจ, ืžื™ืจ ื ื•ืฆืŸ ื‘ืœื•ื™ื– User Space ืคึฟืึทืจ ื“ืขื, ืื™ืŸ ืขืก ืžื™ืจ ื˜ืึธืŸ ื ื™ื˜ ื ื•ืฆืŸ ื™ื ื˜ืขืจืึทืคึผืฅ ืฆื• ืจื•ืคืŸ ืงื™ื™ืŸ ืคึผืจืึธื•ืกื™ื“ื–ืฉืขืจื– ืคื•ืŸ ื“ื™ ืงืขืจืŸ (ื•ื•ืขื’ืŸ ื–ื™ื™ ืื•ื ื˜ืŸ).

ืกืึทืœื•ืฉืึทื ื– ืื™ืŸ ื‘ืึทื ื™ืฆืขืจ ืคึผืœืึทืฅ

ื“ื ืฐืขืœืŸ ืžื™ืจ ื˜ืืŸ ืื–ื•ื™ ืฐื™ ืžื™ืจ ืคืœืขื’ืŸ ื˜ืืŸ ืžื™ื˜ ืืฒืŸ ื’ืึธืคืœ ืื•ืŸ ืฆืฐืฒ ืคื™ืœืื–ืืคืŸ, ืžื™ืจ ืฐืขืœืŸ ื–ื™ืš ื“ืจื™ื™ืขืŸ ืื™ืŸ ื ืฆื™ืงืœ ืื•ืŸ ื•ื•ืืจื˜ืŸ. ืื‘ืขืจ ืื™ืฆื˜ ื•ื•ืขื˜ ืขืก ื–ื™ื™ืŸ ืึทืœืข ืคื™ืœืึธืกืึธืคืขืจืก ืื•ืŸ, ื•ื•ื™ ืขืก ืื™ื–, ื‘ืœื•ื™ื– ืื™ื™ืŸ ื’ืึธืคึผืœ, ื“.ื”. ืžืข ืงืึธืŸ ื–ืึธื’ืŸ, ืึทื– ื ืึธืจ ื“ืขืจ ืคึฟื™ืœืึธืกืึธืฃ, ืฐืึธืก ื”ืึธื˜ ื’ืขื ื•ืžืขืŸ ื“ืขื โ€žื’ืึธืœื“ืขื ืขืจ ื’ืึธืคึผืœโ€œ ืคึฟื•ื ืขื ืงืขืœื ืขืจ, ืฐืขื˜ ืขืกืŸ. ืคึฟืึทืจ ื“ืขื ืžื™ืจ ื ื•ืฆืŸ 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; }, ืึธื‘ืขืจ ืžื™ื˜ ืืคื™ืœื• ืžืขืจ "ืžืึทื’ื™ืฉ" ื•ื•ื™ ืื™ืŸ SpinWait (ื•ื•ืึธืก ื•ื•ืขืจื˜ ื“ืึธืจื˜ืŸ ื’ืขื ื•ืฆื˜). ืื™ืฆื˜ ืฐืฒืก ืขืจ ืฐื™ ืฆื• ืฆืฒืœืŸ ื“ื™ ืฐืึทืจื˜ืขื ืข, ื–ืฒ ืึท ื‘ื™ืกืœ ืฉืœืึธืคึฟืŸ, ืื•ืŸ ื ืึธืš. ื•ื›ื•' ืื™ืŸ ืึทืœื’ืขืžื™ื™ืŸ, ื˜ื•ื˜ ืึทืœืฅ ืžืขื’ืœืขืš ืฆื• ืึทืคึผื˜ืึทืžื™ื™ื–. ืื‘ืขืจ ืžื™ืจ ืžื•ื–ืŸ ื’ืขื“ืขื ืงืขืŸ ืึทื– ื“ืึธืก ืื™ื– ื ืึธืš ื“ืขืจ ื–ืขืœื‘ื™ืงืขืจ ืึทืงื˜ื™ื•ื• ืฆื™ืงืœ ื•ื•ืึธืก ืขืกื˜ ืคึผืจืึทืกืขืกืขืจ ืจืขืกื•ืจืกืŸ ืื•ืŸ ื”ืืœื˜ ื“ื™ ืœื•ื™ืคืŸ, ื•ื•ืึธืก ืงืขื ืขืŸ ืคื™ืจืŸ ืฆื• ื”ื•ื ื’ืขืจ ืื•ื™ื‘ ืื™ื™ื ืขืจ ืคื•ืŸ ื“ื™ ืคื™ืœืึธืกืึธืคืขืจืก ื•ื•ืขืจื˜ ืžืขืจ ื‘ื™ืœื›ืขืจืงื™ื™ึทื˜ ื•ื•ื™ ืื ื“ืขืจืข, ืึธื‘ืขืจ ื”ืื˜ ื ื™ืฉื˜ ืึท ื’ืึธืœื“ืขืŸ ื’ืึธืคึผืœ (ืคึผืจื™ืึธืจื™ื˜ื™ ื™ื ื•ื•ืขืจื–ืฉืึทืŸ ืคึผืจืึธื‘ืœืขื) . ื“ืขืจื™ื‘ืขืจ, ืžื™ืจ ื ื•ืฆืŸ ืขืก ื‘ืœื•ื™ื– ืคึฟืึทืจ ื–ื™ื™ืขืจ ืงื•ืจืฅ ืขื ื“ืขืจื•ื ื’ืขืŸ ืื™ืŸ ืฉืขืจื“ ื–ื›ึผืจื•ืŸ, ืึธืŸ ืงื™ื™ืŸ ื“ืจื™ื˜-ืคึผืึทืจื˜ื™ื™ ืงืึทืœืœืก, ื ืขืกื˜ืขื“ ืœืึทืงืก ืื•ืŸ ืื ื“ืขืจืข ืกืึทืคึผืจื™ื™ื–ื™ื–.

ื’ืขื–ื•ื ื˜-ืคืืกื˜ืขื›ืขืจ ืคื™ืœืึธืกืึธืคืขืจืก ืึธื“ืขืจ ืงืึทืžืคึผืขื˜ื™ื˜ื™ื•ื• .ื ืขื˜ ืคึผืจืึธื’ืจืึทืžืžื™ื ื’

ืฆื™ื™ื›ืขื ื•ื ื’ ืคึฟืึทืจ SpinLock. ื“ ื™ ืฉื˜ืจืื ืŸ ืดืงืืžืคืŸ ืด ืฉื˜ืขื ื“ื™ ืง ืคื ืจ ื“ืข ืจ ื’ืืœื“ืขื ืข ืจ ื’ืืคืœ . ืขืก ื–ืขื ืขืŸ ืคื™ื™ืœื™ืขืจื– - ืื™ืŸ ื“ื™ ืคื™ื’ื•ืจ, ื“ื™ ืื•ื™ืกื’ืขืงืœื™ื‘ืŸ ื’ืขื’ื ื˜. ื“ื™ ืงืึธืจืขืก ื–ืขื ืขืŸ ื ื™ืฉื˜ ื’ืึธืจ ื™ื•ื˜ืึทืœื™ื™ื–ื“: ื‘ืœื•ื™ื– ื•ื•ืขื’ืŸ 2/3 ื“ื•ืจืš ื“ื™ ืคื™ืจ ืคึฟืขื“ืขื.

ืืŸ ืื ื“ืขืจ ืœื™ื™ื–ื•ื ื’ ื“ืึธ ื•ื•ืึธืœื˜ ื–ื™ื™ืŸ ื‘ืœื•ื™ื– ืฆื• ื ื•ืฆืŸ Interlocked.CompareExchange ืžื™ื˜ ื“ืขืจ ื–ืขืœื‘ื™ืงืขืจ ืึทืงื˜ื™ื•ื• ื•ื•ืึทืจื˜ืŸ ื•ื•ื™ ื’ืขื•ื•ื™ื–ืŸ ืื™ืŸ ื“ื™ ืงืึธื“ ืื•ื™ื‘ืŸ (ืื™ืŸ ื“ื™ ื”ื•ื ื’ืขืจื™ืง ืคื™ืœืึธืกืึธืคืขืจืก), ืึธื‘ืขืจ ื“ืึธืก, ื•ื•ื™ ืฉื•ื™ืŸ ื’ืขื–ืื’ื˜, ืงืขืŸ ื˜ืขืึธืจืขื˜ื™ืฉ ืคื™ืจืŸ ืฆื• ื‘ืœืึทืงื™ื ื’.

ืื•ื™ืฃ Interlocked ืขืก ื–ืึธืœ ื–ื™ื™ืŸ ืื ื’ืขื•ื•ื™ื–ืŸ ืึทื– ืขืก ืื™ื– ื ื™ืฉื˜ ื‘ืœื•ื™ื– CompareExchange, ืึธื‘ืขืจ ืื•ื™ืš ืื ื“ืขืจืข ืžืขื˜ื”ืึธื“ืก ืคึฟืึทืจ ืึทื˜ืึธืžื™ืฉืข ืœื™ื™ืขื ืขืŸ ืื•ืŸ ืฉืจื™ื™ึทื‘ืŸ. ืื•ืŸ ื“ื•ืจืš ื“ื™ ื™ื‘ืขืจื›ืึทื–ืขืจื•ื ื’ ืคื•ืŸ ื“ื™ ืขื ื“ืขืจื•ื ื’, ืื™ืŸ ืคืึทืœ ืืŸ ืื ื“ืขืจ ืคืึธื“ืขื ื”ืื˜ ืฆื™ื™ื˜ ืฆื• ืžืึทื›ืŸ ื“ื™ ืขื ื“ืขืจื•ื ื’ืขืŸ (ืœื™ื™ืขื ืขืŸ 1, ืœื™ื™ืขื ืขืŸ 2, ืฉืจื™ื™ึทื‘ืŸ 2, ืฉืจื™ื™ึทื‘ืŸ 1 ืื™ื– ืฉืœืขื›ื˜), ืขืก ืงืขื ืขืŸ ื–ื™ื™ืŸ ื’ืขื•ื•ื™ื™ื ื˜ ืคึฟืึทืจ ืงืึธืžืคึผืœืขืงืก ืขื ื“ืขืจื•ื ื’ืขืŸ ืฆื• ืึท ืื™ื™ืŸ ื•ื•ืขืจื˜ (Interlocked Anything ืžื•ืกื˜ืขืจ) .

ืงืขืจื ืขืœ ืžืึธื“ืข ืกืึทืœื•ืฉืึทื ื–

ืฆื• ื•ื™ืกืžื™ื™ื“ืŸ ื•ื•ื™ื™ืกื˜ื™ื ื’ ืจืขืกื•ืจืกืŸ ืื™ืŸ ืึท ืฉืœื™ื™ืฃ, ืœืึธืžื™ืจ ื–ืขืŸ ื•ื•ื™ ืžื™ืจ ืงืขื ืขืŸ ืคืึทืจืฉืคึผืึทืจืŸ ืึท ืคืึธื“ืขื. ื“ืึธืก ื”ืฒืกื˜, ืฐืฒึทื˜ืขืจ ืื•ื ื“ื–ืขืจ ื‘ืฒึทืฉืคึผื™ืœ, ืœืึธืžื™ืจ ื–ืขืŸ, ืฐื™ ื“ืขืจ ืงืขืœื ืขืจ ืฉืœืึธืคึฟื˜ ื“ืขื ืคึฟื™ืœืึธืกืึธืฃ ืื•ืŸ ืฐืขืงื˜ ืื™ื ื ืึธืจ ืฐืขืŸ ืขืก ืื™ื– ื ื•ื™ื˜ื™ืง. ืขืจืฉื˜ืขืจ, ืœืึธืžื™ืจ ื–ืขืŸ ื•ื•ื™ ืฆื• ื˜ืึธืŸ ื“ืึธืก ื“ื•ืจืš ื“ื™ ืงืขืจืŸ ืžืึธื“ืข ืคื•ืŸ โ€‹โ€‹โ€‹โ€‹ื“ื™ ืึธืคึผืขืจื™ื™ื˜ื™ื ื’ ืกื™ืกื˜ืขื. ืึทืœืข ืกื˜ืจืึทืงื˜ืฉืขืจื– ื“ืึธืจื˜ ื–ืขื ืขืŸ ืึธืคื˜ ืกืœืึธื•ืขืจ ื•ื•ื™ ื™ืขื ืข ืื™ืŸ ื‘ืึทื ื™ืฆืขืจ ืคึผืœืึทืฅ. ืขื˜ืœืขื›ืข ืžืึธืœ ืกืœืึธื•ืขืจ, ืœืžืฉืœ AutoResetEvent ืืคึฟืฉืจ 53 ืžืืœ ืกืœืึธื•ืขืจ SpinLock [ืจื™ื›ื˜ืขืจ]. ืึธื‘ืขืจ ืžื™ื˜ ื–ื™ื™ืขืจ ื”ื™ืœืฃ, ืื™ืจ ืงืขื ืขืŸ ืกื™ื ื’ืงืจืึทื ื™ื™ื– ืคึผืจืึทืกืขืกืึทื– ืื™ื‘ืขืจ ื“ื™ ืกื™ืกื˜ืขื, ื’ืขืจืื˜ืŸ ืึธื“ืขืจ ื ื™ืฉื˜.

ื“ื™ ื’ืจื•ื ื˜ ืงืึทื ืกื˜ืจืึทืงื˜ ื“ืึธ ืื™ื– ื“ื™ ืกืขืžืึทืคืึธืจืข ืคืืจื’ืขืœื™ื™ื’ื˜ ื“ื•ืจืš Dijkstra ืžื™ื˜ ืึท ื”ืึทืœื‘ ื™ืึธืจื”ื•ื ื“ืขืจื˜ ืฆื•ืจื™ืง. ื ืกืขืžืึทืคืึธืจ ืื™ื–, ืคืฉื•ื˜ ืฉื˜ืขืœืŸ, ืึท positive ื™ื ื˜ืึทื“ื–ืฉืขืจ ื’ืขืจืื˜ืŸ ื“ื•ืจืš ื“ื™ ืกื™ืกื˜ืขื, ืื•ืŸ ืฆื•ื•ื™ื™ ืึทืคึผืขืจื™ื™ืฉืึทื ื– ืื•ื™ืฃ ืขืก, ื™ื ืงืจืึทืžืึทื ื˜ ืื•ืŸ ื“ื™ืงืจืึทืžืึทื ื˜. ืื•ื™ื‘ ืขืก ืคื™ื™ืœื– ืฆื• ืคืึทืจืžื™ื ืขืจืŸ, ื ื•ืœ, ื“ื™ ืคืึทืš ืคืึธื“ืขื ืื™ื– ืืคื’ืขืฉื˜ืขืœื˜. ื•ื•ืขืŸ ื“ื™ ื ื•ืžืขืจ ืื™ื– ื™ื ืงืจืึทืžืึทื ื˜ื™ื“ ื“ื•ืจืš ืขื˜ืœืขื›ืข ืื ื“ืขืจืข ืึทืงื˜ื™ื•ื• ืคืึธื“ืขื / ืคึผืจืึธืฆืขืก, ื“ื™ ืคึฟืขื“ืขื ื–ืขื ืขืŸ ืกืงื™ืคึผื˜ ืื•ืŸ ื“ื™ ืกืขืžืึทืคืึธืจืข ืื™ื– ื•ื•ื™ื“ืขืจ ื“ื™ืงืจื™ืกื˜ ื“ื•ืจืš ื“ื™ ื“ื•ืจื›ื’ืขื’ืื ื’ืขืŸ ื ื•ืžืขืจ. ืžืขืŸ ืงืขืŸ ื–ื™ืš ืคืืจืฉื˜ืขืœืŸ ื‘ืื ืขืŸ ืื™ืŸ ื ื‘ืื˜ืœื ืขืง ืžื™ื˜ ื ืกืขืžืืคืืจ. .ื ืขื˜ ืึธืคืคืขืจืก ืขื˜ืœืขื›ืข ืงืึทื ืกื˜ืจืึทืงืฉืึทื ื– ืžื™ื˜ ืขื ืœืขืš ืคืึทื ื’ืงืฉืึทื ืึทืœื™ื˜ื™: AutoResetEvent, ManualResetEvent, Mutex ืื•ืŸ ื–ื™ืš Semaphore. ืžื™ืจ ื•ื•ืขืœืŸ ื ื•ืฆืŸ AutoResetEvent, ื“ืึธืก ืื™ื– ื“ื™ ืกื™ืžืคึผืœืึทืกื˜ ืคื•ืŸ ื“ื™ ืงืึทื ืกื˜ืจืึทืงืฉืึทื ื–: ื‘ืœื•ื™ื– ืฆื•ื•ื™ื™ ื•ื•ืึทืœื•ืขืก 0 ืื•ืŸ 1 (ืคืึทืœืฉ, ืืžืช). ืื™ืจ ืฉื™ื˜ื” WaitOne() ื‘ืœืึทืงืก ื“ื™ ืคืึทืš ืคืึธื“ืขื ืื•ื™ื‘ ื“ื™ ื•ื•ืขืจื˜ ืื™ื– 0, ืื•ืŸ ืื•ื™ื‘ 1, ืœืึธื•ื•ืขืจืก ืขืก ืฆื• 0 ืื•ืŸ ืกืงื™ืคึผืก ืขืก. ื ืฉื™ื˜ื” Set() ื”ืฒื‘ื˜ ื–ื™ืš ืืฑืฃ ืฆื• 1 ืื•ืŸ ืœืึธื–ื˜ ืึทืจืฒึทืŸ ืืฒืŸ ืงืขืœื ืขืจ, ืฐืึธืก ืœืึธื–ื˜ ื–ื™ืš ืฐื™ื“ืขืจ ืึทืจืึธืคึผ ืฆื• 0. ืคึฟื™ืจื˜ ื–ื™ืš ืฐื™ ืึท ืžืขื˜ืจืึธึพื˜ืจืึทื ืกื˜ื™ื™ืœ.

ืœืึธืžื™ืจ ืงืึธืžืคึผืœื™ืฆื™ืจืŸ ื“ื™ ืœื™ื™ื–ื•ื ื’ ืื•ืŸ ื ื•ืฆืŸ ื“ืขื ืฉืœืึธืก ืคึฟืึทืจ ื™ืขื“ืขืจ ืคื™ืœืึธืกืึธืฃ, ืื•ืŸ ื ื™ืฉื˜ ืคึฟืึทืจ ืึทืœืข ืื™ืŸ ืึทืžืึธืœ. ื™ืขื ืข. ืื™ืฆื˜ ืงืขื ืขืŸ ื–ื™ื™ืŸ ืขื˜ืœืขื›ืข ืคื™ืœืึธืกืึธืคืขืจืก ืื™ืŸ ืึทืžืึธืœ, ืื•ืŸ ื ื™ืฉื˜ ืื™ื™ื ืขืจ. ืื‘ืขืจ ืžื™ืจ ื•ื•ื™ื“ืขืจ ืคืึทืจืฉืคึผืึทืจืŸ ืึทืงืกืขืก ืฆื• ื“ื™ ื˜ื™ืฉ ืื™ืŸ ืกื“ืจ ืฆื• ืจื™ื›ื˜ื™ืง, ืึทื•ื•ื•ื™ื“ื™ื ื’ ืจืึทืกืขืก (ืจืึทืกืข ื˜ื ืึธื™ื), ื ืขืžืขืŸ ื–ื™ื›ืขืจืขืขืฅ.

// ะ”ะปั ะฑะปะพะบะธั€ะพะฒะฐะฝะธั ะพั‚ะดะตะปัŒะฝะพะณะพ ั„ะธะปะพัะพั„ะฐ.
// ะ˜ะฝะธั†ะธะฐะปะธะทะธั€ัƒะตั‚ัั: 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 ืขื˜ืง ื“ื™ ืžืขืจืกื˜ ืคืึธืœืงืก ืคึผืœืึทืŸ ื“ืึธ ืื™ื– Monitor, ื•ื•ื™ื™ึทืœ ืื™ืŸ C # ืขืก ืื™ื– ืึท ื‘ืึทื•ื•ื•ืกื˜ lock ืกื™ื ื˜ืึทืงืก. Monitor ื“ืึธืก ืื™ื– ื“ืขืจ ื–ืขืœื‘ื™ืงืขืจ ืกืขืžืึทืคืึธืจืข ืžื™ื˜ ืึท ืžืึทืงืกื™ืžื•ื ื•ื•ืขืจื˜ ืคื•ืŸ 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 ืกื™ื ื˜ืึทืงืก ื”ืื˜ ืคึผืึทืกืงื•ื“ื ืข ืกืึทืคึผืจื™ื™ื–ื™ื–. ืจืขืงืึธืžืขื ื“ื™ืจืŸ ืฆื• ื ื•ืฆืŸ Monitor ื’ืœื™ื™ึทืš [ืจื™ื›ื˜ืขืจ] [ืขืจื™ืง ืœื™ืคึผืขืจื˜]. ืื™ื™ื ืขืจ ืคื•ืŸ ื–ื™ื™ ืื™ื– ืึทื– lock ืฉื˜ืขื ื“ื™ืง ืื•ื™ืก ืคื•ืŸ Monitor, ืืคื™ืœื• ืื•ื™ื‘ ืขืก ืื™ื– ื’ืขื•ื•ืขืŸ ืึท ื•ื™ืกื ืขื, ืื™ืŸ ื•ื•ืึธืก ืคืึทืœ ืืŸ ืื ื“ืขืจ ืคืึธื“ืขื ืงืขืŸ ื˜ื•ื™ืฉืŸ ื“ื™ ืฉืขืจื“ ื–ื›ึผืจื•ืŸ ืฉื˜ืึทื˜. ืื™ืŸ ืึทื–ืึท ืงืึทืกืขืก, ืขืก ืื™ื– ืึธืคื˜ ื‘ืขืกืขืจ ืฆื• ื’ื™ื™ืŸ ืฆื• ื“ืขื“ืœืึทืง ืึธื“ืขืจ ืขืคืขืก ื‘ืขืฉืึธืœืขื ืคืึทืจืขื ื“ื™ืงืŸ ื“ื™ ืคึผืจืึธื’ืจืึทื. ืืŸ ืื ื“ืขืจ ื™ื‘ืขืจืจืึทืฉืŸ ืื™ื– ืึทื– ืžืึธื ื™ื˜ืึธืจ ื ื™ืฆื˜ ืกื™ื ื’ืงืจืึทื ืึทื–ื™ื™ืฉืึทืŸ ื‘ืœืึทืงืก (SyncBlock), ื•ื•ืึธืก ื–ืขื ืขืŸ ืคืึธืจืฉื˜ืขืœืŸ ืื™ืŸ ืึทืœืข ืึทื‘ื“ื–ืฉืขืงืฅ. ื“ืขืจื™ื‘ืขืจ, ืื•ื™ื‘ ืึท ื™ื ืึทืคึผืจืึธื•ืคึผืจื™ื™ื˜ ื›ื™ื™ืคืขืฅ ืื™ื– ืื•ื™ืกื’ืขืงืœื™ื‘ืŸ, ืื™ืจ ืงืขื ืขืŸ ืœื™ื™ื›ื˜ ื‘ืึทืงื•ืžืขืŸ ืึท ื“ืขื“ืœืึทืง (ืœืžืฉืœ, ืื•ื™ื‘ ืื™ืจ ืฉืœืึธืก ืื•ื™ืฃ ืึท ื™ื ื˜ืขืจื ืขื“ ืฉื˜ืจื™ืงืœ). ืžื™ืจ ื ื•ืฆืŸ ื“ื™ ืฉื˜ืขื ื“ื™ืง ืคืึทืจื‘ืึธืจื’ืŸ ื›ื™ื™ืคืขืฅ ืคึฟืึทืจ ื“ืขื.

ื“ื™ ืงืึธื ื“ื™ื˜ื™ืึธืŸ ื•ื•ืึทืจื™ืึทื‘ืœืข ืžื•ืกื˜ืขืจ ืึทืœืึทื•ื– ืื™ืจ ืฆื• ืžืขืจ ืงืึทื ืกื™ื™ืกืœื™ ื™ื ืกื˜ืจื•ืžืขื ื˜ ื“ื™ ื“ืขืจื•ื•ืึทืจื˜ื•ื ื’ ืคื•ืŸ ืขื˜ืœืขื›ืข ืงืึธืžืคึผืœืขืงืก ืฆื•ืฉื˜ืึทื ื“. ืื™ืŸ .ื ืขื˜, ืขืก ืื™ื– ื“ืขืจืขื ื“ื™ืงื˜, ืื™ืŸ ืžื™ื™ืŸ ืžื™ื™ื ื•ื ื’, ื•ื•ื™ื™ึทืœ ืื™ืŸ ื˜ืขืึธืจื™ืข, ืขืก ื–ืึธืœ ื–ื™ื™ืŸ ืขื˜ืœืขื›ืข ืงื™ื•ื– ืื•ื™ืฃ ืขื˜ืœืขื›ืข ื•ื•ืขืจื™ืึทื‘ืึทืœื– (ื•ื•ื™ ืื™ืŸ Posix ืคึฟืขื“ืขื), ืื•ืŸ ื ื™ืฉื˜ ืื•ื™ืฃ ืื™ื™ืŸ ืœืึธื•ืง. ื“ืขืžืืœ ื˜ ื”ื ื˜ ืžืข ืŸ ื– ืฒ ื’ืขืงืขื  ื˜ ืžืื› ืŸ ืคื ืจ ืืœ ืข ืคื™ืœืืกืืคืŸ . ืึธื‘ืขืจ ืืคื™ืœื• ืื™ืŸ ื“ืขื ืคืึธืจืขื, ืขืก ืึทืœืึทื•ื– ืื™ืจ ืฆื• ืจืขื“ื•ืฆื™ืจืŸ ื“ื™ ืงืึธื“.

ืคื™ืœืข ืคื™ืœืึธืกืึธืคืขืจืก ืึธื“ืขืจ async / await

ืึธื•ืงื™ื™, ืื™ืฆื˜ ืžื™ืจ ืงืขื ืขืŸ ื™ืคืขืงื˜ื™ื•ื•ืœื™ ืคืึทืจืฉืคึผืึทืจืŸ ืคึฟืขื“ืขื. ืึธื‘ืขืจ ื•ื•ืึธืก ืื•ื™ื‘ ืžื™ืจ ื”ืึธื‘ืŸ ืึท ืคึผืœืึทืฅ ืคื•ืŸ ืคื™ืœืึธืกืึธืคืขืจืก? 100? 10000? ืคึฟืึทืจ ื‘ื™ื™ึทืฉืคึผื™ืœ, ืžื™ืจ ื‘ืืงื•ืžืขืŸ 100000 ืจื™ืงื•ื•ืขืก ืฆื• ื“ื™ ื•ื•ืขื‘ ืกืขืจื•ื•ืขืจ. ืขืก ื•ื•ืขื˜ ื–ื™ื™ืŸ ืึธื•ื•ื•ืขืจื›ืขื“ ืฆื• ืฉืึทืคึฟืŸ ืึท ืคืึธื“ืขื ืคึฟืึทืจ ื™ืขื“ืขืจ ื‘ืงืฉื”, ื•ื•ื™ื™ึทืœ ืึทื–ื•ื™ ืคื™ืœืข ืคึฟืขื“ืขื ื•ื•ืขืœืŸ ื ื™ืฉื˜ ืœื•ื™ืคืŸ ืื™ืŸ ืคึผืึทืจืึทืœืขืœ. ื•ื•ืขื˜ ื ืึธืจ ืœื•ื™ืคืŸ ื•ื•ื™ ืคื™ืœืข ื•ื•ื™ ืขืก ื–ืขื ืขืŸ ืœืึทื“ื–ืฉื™ืงืึทืœ ืงืึธืจืขืก (ืื™ืš ื”ืึธื‘ืŸ 4). ืื•ืŸ ืึทืœืขืžืขืŸ ืึทื ื“ืขืจืฉ ื•ื•ืขื˜ ื ืึธืจ ื ืขืžืขืŸ ืึทื•ื•ืขืง ืจืขืกื•ืจืกืŸ. ืื™ื™ืŸ ืœื™ื™ื–ื•ื ื’ ืฆื• ื“ืขื ืคึผืจืึธื‘ืœืขื ืื™ื– ื“ื™ ืึทืกื™ื ืง / ื“ืขืจื•ื•ืึทืจื˜ืŸ ืžื•ืกื˜ืขืจ. ื–ื™ื™ืŸ ื’ืขื“ืึทื ืง ืื™ื– ืึทื– ื“ื™ ืคึฟื•ื ืงืฆื™ืข ื˜ื•ื˜ ื ื™ืฉื˜ ื”ืึทืœื˜ืŸ ื“ื™ ืคืึธื“ืขื ืื•ื™ื‘ ืขืก ื“ืึทืจืฃ ืฆื• ื•ื•ืึทืจื˜ืŸ ืคึฟืึทืจ ืขืคึผืขืก ืฆื• ืคืึธืจื–ืขืฆืŸ. ืื•ืŸ ื•ื•ืขืŸ ืขืก ื˜ื•ื˜ ืขืคึผืขืก, ืขืก ืจื™ืกื•ืžื– ื–ื™ื™ึทืŸ ื“ื•ืจื›ืคื™ืจื•ื ื’ (ืึธื‘ืขืจ ื ื™ื˜ ื“ืึทื•ื•ืงืข ืื•ื™ืฃ ื“ื™ ื–ืขืœื‘ืข ืคืึธื“ืขื!). ืื™ืŸ ืื•ื ื“ื–ืขืจ ืคืึทืœ, ืžื™ืจ ื•ื•ืขืœืŸ ื•ื•ืึทืจื˜ืŸ ืคึฟืึทืจ ื“ื™ ื’ืึธืคึผืœ.

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 ืื™ื– ืื™ื‘ืขืจื’ืขื–ืขืฆื˜ ืื™ืŸ ืึท ื˜ืจื™ืงื™ ืฉื˜ืึทื˜ ืžืึทืฉื™ืŸ ื•ื•ืึธืก ื’ืœื™ื™ืš ืงืขืจื˜ ื–ื™ื™ืŸ ื™ื ืขืจืœืขืš Task. ื“ื•ืจืš ืขืก, ืื™ืจ ืงืขื ืขืŸ ื•ื•ืึทืจื˜ืŸ ืคึฟืึทืจ ื“ื™ ืงืึทืžืคึผืœื™ืฉืึทืŸ ืคื•ืŸ ื“ืขื ืื•ืคึฟืŸ, ื‘ืึธื˜ืœ ืžืึทื›ืŸ ืขืก ืื•ืŸ ืึทืœืฅ ืึทื ื“ืขืจืฉ ืื™ืจ ืงืขื ืขืŸ ื˜ืึธืŸ ืžื™ื˜ ื˜ืึทืกืง. ืื™ืŸ ื“ืขื ืื•ืคึฟืŸ, ื“ื™ ืฉื˜ืึทื˜ ืžืึทืฉื™ืŸ ืงืึธื ื˜ืจืึธืœืก ื“ื™ ื“ื•ืจื›ืคื™ืจื•ื ื’. ื“ื™ ื“ื ืึธ ืฉื•ืจื” ืื™ื– ืึทื– ืื•ื™ื‘ ืขืก ืื™ื– ืงื™ื™ืŸ ืคืึทืจื”ืึทืœื˜ืŸ, ื“ื™ ื“ื•ืจื›ืคื™ืจื•ื ื’ ืื™ื– ืกื™ื ื˜ืฉืจืึธื ืึธื•ืก, ืื•ืŸ ืื•ื™ื‘ ืขืก ืื™ื–, ื“ืขืจ ืคืึธื“ืขื ืื™ื– ืคืจื™ื™. ืคึฟืึทืจ ืึท ื‘ืขืกืขืจ ืคืืจืฉื˜ืื ื“ ืคื•ืŸ ื“ืขื, ืขืก ืื™ื– ื‘ืขืกืขืจ ืฆื• ืงื•ืงืŸ ืื™ืŸ ื“ืขื ืฉื˜ืึทื˜ ืžืึทืฉื™ืŸ. ืื™ืจ ืงืขื ืขืŸ ืžืึทื›ืŸ ืงื™ื™ื˜ืŸ ืคื•ืŸ ื“ื™ async / await ืžืขื˜ื”ืึธื“ืก.

ื–ืืœ ืก ืคึผืจื•ื‘ื™ืจืŸ. ืึทืจื‘ืขื˜ ืคื•ืŸ 100 ืคื™ืœืึธืกืึธืคืขืจืก ืื•ื™ืฃ ืึท ืžืึทืฉื™ืŸ ืžื™ื˜ 4 ืœืึทื“ื–ืฉื™ืงืึทืœ ืงืึธืจืขืก, 8 ืกืขืงื•ื ื“ืขืก. ื“ื™ ืคืจื™ืขืจื“ื™ืงืข ืœื™ื™ื–ื•ื ื’ ืžื™ื˜ ืžืึธื ื™ื˜ืึธืจ ื‘ืœื•ื™ื– ื’ืขืœืืคืŸ ื“ื™ ืขืจืฉื˜ืขืจ 4 ืคึฟืขื“ืขื ืื•ืŸ ื“ื™ ืžื ื•ื—ื” ื”ืื˜ ื ื™ืฉื˜ ืœื•ื™ืคืŸ ืื™ืŸ ืึทืœืข. ื™ืขื“ืขืจ ืคื•ืŸ ื“ื™ 4 ืคึฟืขื“ืขื ืื™ื– ืœื™ื™ื“ื™ืง ืคึฟืึทืจ ื•ื•ืขื’ืŸ 2ms. ืื•ืŸ ื“ื™ ืึทืกื™ื ืง / ื“ืขืจื•ื•ืึทืจื˜ืŸ ืœื™ื™ื–ื•ื ื’ ืื™ื– ื’ืขื•ื•ืขืŸ ืึทืœืข 100, ืžื™ื˜ ืึท ื“ื•ืจื›ืฉื ื™ื˜ืœืขืš ื•ื•ืึทืจื˜ืŸ ืคื•ืŸ 6.8 ืกืขืงื•ื ื“ืขืก ื™ืขื“ืขืจ. ืคื•ืŸ ืงื•ืจืก, ืื™ืŸ ืคืึทืงื˜ื™ืฉ ืกื™ืกื˜ืขืžืขืŸ ืœื™ื™ื“ื™ืง ืคึฟืึทืจ 6 ืกืขืงื•ื ื“ืขืก ืื™ื– ืึทื ืึทืงืกืขืคึผื˜ืึทื‘ืึทืœ ืื•ืŸ ืขืก ืื™ื– ื‘ืขืกืขืจ ื ื™ืฉื˜ ืฆื• ืคึผืจืึธืฆืขืก ืึทื–ื•ื™ ืคื™ืœืข ืจื™ืงื•ื•ืขืก ื•ื•ื™ ื“ืึธืก. ื“ื™ ืœื™ื™ื–ื•ื ื’ ืžื™ื˜ ืžืึธื ื™ื˜ืึธืจ ืื™ื– ื’ืขื•ื•ืขืŸ ื ื™ื˜ ืกืงืึทืœืึทื‘ืœืข ื‘ื™ื™ึท ืึทืœืข.

ืกืึธืฃ

ื•ื•ื™ ืื™ืจ ืงืขื ืขืŸ ื–ืขืŸ ืคื•ืŸ ื“ื™ ืงืœื™ื™ืŸ ื‘ื™ื™ืฉืคื™ืœืŸ,. ื ืขืฅ ืฉื˜ื™ืฆื˜ ืคื™ืœืข ืกื™ื ื’ืงืจืึทื ืึทื–ื™ื™ืฉืึทืŸ ืงืึทื ืกื˜ืจืึทืงืฉืึทื ื–. ืึธื‘ืขืจ, ืขืก ืื™ื– ื ื™ื˜ ืฉื˜ืขื ื“ื™ืง ืงืœืึธืจ ื•ื•ื™ ื“ืขืจ ื˜ืึธื’ ื•ื•ื™ ืฆื• ื ื•ืฆืŸ ื–ื™ื™. ืื™ืš ื”ืึธืคึฟืŸ ื“ืขื ืึทืจื˜ื™ืงืœ ืื™ื– ื’ืขื•ื•ืขืŸ ื ื•ืฆื™ืง. ืคึฟืึทืจ ืื™ืฆื˜, ื“ืึธืก ืื™ื– ื“ืขืจ ืกื•ืฃ, ืึธื‘ืขืจ ืขืก ื–ืขื ืขืŸ ื ืึธืš ืึท ืคึผืœืึทืฅ ืคื•ืŸ ื˜ืฉื™ืงืึทื•ื•ืข ื–ืื›ืŸ ืœื™ื ืงืก, ืœืžืฉืœ, ืคืึธื“ืขื-ื–ื™ื›ืขืจ ื–ืึทืžืœื•ื ื’ืขืŸ, TPL Dataflow, ืจื™ืึทืงื˜ื™ื•ื• ืคึผืจืึธื’ืจืึทืžืžื™ื ื’, ื•ื•ื™ื™ื›ื•ื•ืืจื’ ื˜ืจืึทื ืกืึทืงื˜ื™ืึธืŸ ืžืึธื“ืขืœ, ืขื˜ืง.

ืงื•ื•ืืœืŸ

ืžืงื•ืจ: www.habr.com

ืœื™ื™ื’ืŸ ืึท ื‘ืึทืžืขืจืงื•ื ื’