
ΠΠ΅ΠΊΠ° Π΄Π° Π²ΠΈΠ΄ΠΈΠΌ ΠΊΠ°ΠΊ Π΅ ΡΡΡΡΠΎΠ΅Π½ΠΎ ΠΊΠΎΠ½ΠΊΡΡΠ΅Π½ΡΠ½ΠΎΡΠΎ ΠΈ ΠΏΠ°ΡΠ°Π»Π΅Π»Π½ΠΎΡΠΎ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΈΡΠ°Π½Π΅ Π² .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.

ΠΠ° ΡΡ Π΅ΠΌΠ°ΡΠ°, Π±Π»ΠΎΠΊΠΈΡΠ°Π½Π΅ΡΠΎ Π½Π° ΠΏΠΎΡΠΎΠΊΠΎΠ²Π΅ΡΠ΅ (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 ΠΏΡΡΠΈ ΠΏΠΎ-ΠΌΠ°Π»ΠΊΠΎ ΠΎΡ Π»ΠΎΡΠΈΡΠ΅. Π’Π°ΠΊΠ° ΡΠ΅ ΠΌΠ°Π»ΠΊΠ° Π³ΡΠ΅ΡΠΊΠ° Π² ΠΊΠΎΠ΄Π° Π²ΠΎΠ΄ΠΈ Π΄ΠΎ ΡΠΏΠ°Π΄ Π½Π° ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»Π½ΠΎΡΡΡΠ°. Π’ΡΠΊ Π΅ Π²Π°ΠΆΠ½ΠΎ Π΄Π° ΡΠ΅ ΠΎΡΠ±Π΅Π»Π΅ΠΆΠΈ, ΡΠ΅ ΡΡΡΠ΅ΡΡΠ²ΡΠ²Π° ΡΡΠ΄ΠΊΠ° ΡΠΈΡΡΠ°ΡΠΈΡ, ΠΊΠΎΠ³Π°ΡΠΎ Π²ΡΠΈΡΠΊΠΈ ΡΠΈΠ»ΠΎΡΠΎΡΠΈ Π²Π·Π΅ΠΌΠ°Ρ Π»ΡΠ²Π°ΡΠ° Π²ΠΈΠ»ΠΈΡΠ°, Π΄ΡΡΠ½Π°ΡΠ° Π΅ Π½Π΅Π΄ΠΎΡΡΡΠΏΠ½Π°, ΡΠ΅ ΠΎΡΡΠ°Π²ΡΡ Π»ΡΠ²Π°ΡΠ°, ΡΠ°ΠΊΠ°Ρ, Π²Π·Π΅ΠΌΠ°Ρ ΠΎΡΠ½ΠΎΠ²ΠΎ Π»ΡΠ²Π°ΡΠ° ΠΈ Ρ.Π½. Π’Π°Π·ΠΈ ΡΠΈΡΡΠ°ΡΠΈΡ ΡΡΡΠΎ Π΅ Π³Π»Π°Π΄, ΠΏΠΎ-ΡΠΊΠΎΡΠΎ ΠΏΠΎΠ΄ΠΎΠ±Π½Π° Π½Π° Π²Π·Π°ΠΈΠΌΠ½Π° Π±Π»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΠ°. ΠΠ΅ ΡΡΠΏΡΡ Π΄Π° Ρ ΠΏΠΎΠ²ΡΠΎΡΡ. ΠΠΎ-Π΄ΠΎΠ»Ρ Π΅ ΠΈΠ·ΠΎΠ±ΡΠ°ΠΆΠ΅Π½ΠΈΠ΅ Π½Π° ΡΠΈΡΡΠ°ΡΠΈΡ, ΠΊΠΎΠ³Π°ΡΠΎ Π΄Π²Π°ΠΌΠ° Π»ΠΎΡΠΈ ΡΠΈΠ»ΠΎΡΠΎΡΠΈ Π²Π·Π΅ΠΌΠ°Ρ ΠΈ Π΄Π²Π΅ΡΠ΅ Π²ΠΈΠ»ΠΈΡΠΈ, Π° Π΄Π²Π°ΠΌΠ° Π΄ΠΎΠ±ΡΠΈ Π³Π»Π°Π΄ΡΠ²Π°Ρ.

Π’ΡΠΊ ΡΠ΅ Π²ΠΈΠΆΠ΄Π°, ΡΠ΅ Π½ΠΈΡΠΊΠΈΡΠ΅ ΠΏΠΎΠ½ΡΠΊΠΎΠ³Π° ΡΠ΅ ΡΡΠ±ΡΠΆΠ΄Π°Ρ ΠΈ ΠΎΠΏΠΈΡΠ²Π°Ρ Π΄Π° ΠΏΠΎΠ»ΡΡΠ°Ρ ΡΠ΅ΡΡΡΡ. ΠΠ²Π° ΠΎΡ ΡΠ΅ΡΠΈΡΠΈ ΡΠ΄ΡΠ° Π½ΠΈΡΠΎ Π½Π΅ ΠΏΡΠ°Π²ΡΡ (Π·Π΅Π»Π΅Π½ΠΈΡΡ Π³ΡΠ°ΡΠΈΠΊ ΠΎΡΠ³ΠΎΡΠ΅).
Π‘ΠΌΡΡΡ Π½Π° ΡΠΈΠ»ΠΎΡΠΎΡΠ°
Π ΠΎΡΠ΅ Π΅Π΄Π½Π° ΠΏΡΠΎΠ±Π»Π΅ΠΌΠ°, ΠΊΠΎΡΡΠΎ ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΏΡΠ΅ΠΊΡΡΠ½Π΅ ΡΠ»Π°Π²Π½ΠΈΡ ΠΎΠ±ΡΠ΄ Π½Π° ΡΠΈΠ»ΠΎΡΠΎΡΠΈΡΠ΅ β Π°ΠΊΠΎ Π΅Π΄ΠΈΠ½ ΠΎΡ ΡΡΡ
Π²Π½Π΅Π·Π°ΠΏΠ½ΠΎ ΡΠΌΡΠ΅ Ρ Π²ΠΈΠ»ΠΈΡΠΈ Π² ΡΡΡΠ΅ (ΠΈ Π΄Π° Π±ΡΠ΄Π΅ ΠΏΠΎΠ³ΡΠ΅Π±Π°Π½ ΡΠ°ΠΊΠ°). Π’ΠΎΠ³Π°Π²Π° ΡΡΡΠ΅Π΄ΠΈΡΠ΅ ΡΠ΅ ΠΎΡΡΠ°Π½Π°Ρ Π±Π΅Π· ΠΎΠ±ΡΠ΄. ΠΡΠΈΠΌΠ΅Ρ Π·Π° ΠΊΠΎΠ΄ Π·Π° ΡΠΎΠ·ΠΈ ΡΠ»ΡΡΠ°ΠΉ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΠΈΠ·ΠΌΠΈΡΠ»ΠΈΡΠ΅ ΡΠ°ΠΌΠΈ, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ ΡΠ΅ ΠΈΠ·ΠΊΠ»ΡΡΠ²Π° 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), Π°ΠΊΠΎ Π΅Π΄ΠΈΠ½ ΠΎΡ ΡΠΈΠ»ΠΎΡΠΎΡΠΈΡΠ΅ ΡΡΠ°Π½Π΅ ΠΏΡΠΈΠΎΡΠΈΡΠ΅ΡΠ΅Π½ ΠΏΡΠ΅Π΄ Π΄ΡΡΠ³ΠΈΡΠ΅, Π½ΠΎ Π½Π΅ ΡΠ°Π·ΠΏΠΎΠ»Π°Π³Π° ΡΡΡ Π·Π»Π°ΡΠ½Π°ΡΠ° Π²ΠΈΠ»ΠΈΡΠ°. ΠΠ°ΡΠΎΠ²Π° Π³ΠΎ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ ΡΠ°ΠΌΠΎ Π·Π° ΠΌΠ½ΠΎΠ³ΠΎ, ΠΌΠ½ΠΎΠ³ΠΎ ΠΊΡΠ°ΡΠΊΠΈ ΠΏΡΠΎΠΌΠ΅Π½ΠΈ Π² ΠΎΠ±ΡΠ°ΡΠ° ΠΏΠ°ΠΌΠ΅Ρ, Π±Π΅Π· Π½ΠΈΠΊΠ°ΠΊΠ²ΠΈ Π²ΡΠ½ΡΠ½ΠΈ ΠΈΠ·Π²ΠΈΠΊΠ²Π°Π½ΠΈΡ, Π²Π»ΠΎΠΆΠ΅Π½ΠΈ Π±Π»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΠΈ ΠΈ Ρ.Π½. ΠΈΠ·Π½Π΅Π½Π°Π΄ΠΈ.

ΠΠ»ΡΡΡΡΠ°ΡΠΈΡ Π·Π° 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, ΡΠ΅Π°ΠΊΡΠΈΠ²Π½ΠΎ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΈΡΠ°Π½Π΅, ΠΌΠΎΠ΄Π΅Π» Π½Π° ΡΠΎΡΡΡΠ΅ΡΠ½ΠΈ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΈ ΠΈ Π΄Ρ.
ΠΠ·ΡΠΎΡΠ½ΠΈΡΠΈ
- ΠΠΈΠ·ΡΠ°Π»ΠΈΠ·Π°ΡΠΈΡ Π½Π° ΠΏΠΎΡΠΎΠΊΠΎΠ²Π΅ΡΠ΅:
- MSDN: , ΠΈ Π΄Ρ.
- [Π ΠΈΡ ΡΠ΅Ρ] β CLR via C#, ΠΠΆΠ΅ΡΡΠΈ Π ΠΈΡ ΡΠ΅Ρ
- [ΠΡΠΈΠΊ ΠΠΈΠΏΠΏΠ΅ΡΡ] β
- ΠΠ°ΡΡΠΈΠ½Π° β Β«Π’Π°Π½Π΅Ρ ΡΡΠ΅Π΄ ΠΌΠ΅ΡΠΎΠ²Π΅Β», Π. Π‘Π΅ΠΌΠΈΡΠ°Π΄ΡΠΊΠΈ
ΠΠ·ΡΠΎΡΠ½ΠΈΠΊ: habr.com
