ΠΠ΅ΠΊΠ° Π΄Π° ΡΠ°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ ΠΊΠ°ΠΊ ΡΠ°Π±ΠΎΡΠΈ Π΅Π΄Π½ΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½ΠΎΡΠΎ ΠΈ ΠΏΠ°ΡΠ°Π»Π΅Π»Π½ΠΎΡΠΎ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΈΡΠ°Π½Π΅ Π² .Net, ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΉΠΊΠΈ ΠΏΡΠΈΠΌΠ΅ΡΠ° Π½Π° ΠΏΡΠΎΠ±Π»Π΅ΠΌΠ° Ρ ΠΎΠ±ΡΠ΄Π²Π°ΡΠΈΡΠ΅ ΡΠΈΠ»ΠΎΡΠΎΡΠΈ. ΠΠ»Π°Π½ΡΡ Π΅ ΡΠ»Π΅Π΄Π½ΠΈΡΡ, ΠΎΡ ΡΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·ΠΈΡΠ°Π½Π΅ΡΠΎ Π½Π° ΠΏΠΎΡΠΎΠΊ/ΠΏΡΠΎΡΠ΅Ρ Π΄ΠΎ ΠΌΠΎΠ΄Π΅Π»Π° Π½Π° Π°ΠΊΡΡΠΎΡΠ° (Π² ΡΠ»Π΅Π΄Π²Π°ΡΠΈΡΠ΅ ΡΠ°ΡΡΠΈ). Π‘ΡΠ°ΡΠΈΡΡΠ° ΠΌΠΎΠΆΠ΅ Π΄Π° Π΅ ΠΏΠΎΠ»Π΅Π·Π½Π° Π·Π° ΠΏΡΡΠ²ΠΎ Π·Π°ΠΏΠΎΠ·Π½Π°Π½ΡΡΠ²ΠΎ ΠΈΠ»ΠΈ Π·Π° ΠΎΠΏΡΠ΅ΡΠ½ΡΠ²Π°Π½Π΅ Π½Π° Π·Π½Π°Π½ΠΈΡΡΠ°.
ΠΠ°ΡΠΎ ΠΈΠ·ΠΎΠ±ΡΠΎ Π΄Π° Π·Π½Π°Π΅ΡΠ΅ ΠΊΠ°ΠΊ Π΄Π° Π½Π°ΠΏΡΠ°Π²ΠΈΡΠ΅ ΡΠΎΠ²Π°? Π’ΡΠ°Π½Π·ΠΈΡΡΠΎΡΠΈΡΠ΅ Π΄ΠΎΡΡΠΈΠ³Π°Ρ ΠΌΠΈΠ½ΠΈΠΌΠ°Π»Π½ΠΈΡ ΡΠΈ ΡΠ°Π·ΠΌΠ΅Ρ, Π·Π°ΠΊΠΎΠ½ΡΡ Π½Π° ΠΡΡ Π΄ΠΎΡΡΠΈΠ³Π° Π³ΡΠ°Π½ΠΈΡΠ°ΡΠ° Π½Π° ΡΠΊΠΎΡΠΎΡΡΡΠ° Π½Π° ΡΠ²Π΅ΡΠ»ΠΈΠ½Π°ΡΠ° ΠΈ ΡΠ»Π΅Π΄ΠΎΠ²Π°ΡΠ΅Π»Π½ΠΎ ΡΠ΅ Π½Π°Π±Π»ΡΠ΄Π°Π²Π° Π½Π°ΡΠ°ΡΡΠ²Π°Π½Π΅ Π½Π° Π±ΡΠΎΡ; ΠΌΠΎΠ³Π°Ρ Π΄Π° ΡΠ΅ ΠΏΡΠ°Π²ΡΡ ΠΏΠΎΠ²Π΅ΡΠ΅ ΡΡΠ°Π½Π·ΠΈΡΡΠΎΡΠΈ. Π ΡΡΡΠΎΡΠΎ Π²ΡΠ΅ΠΌΠ΅ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎΡΠΎ Π΄Π°Π½Π½ΠΈ ΡΠ°ΡΡΠ΅ ΠΈ ΠΏΠΎΡΡΠ΅Π±ΠΈΡΠ΅Π»ΠΈΡΠ΅ ΠΎΡΠ°ΠΊΠ²Π°Ρ Π½Π΅Π·Π°Π±Π°Π²Π΅Π½ ΠΎΡΠ³ΠΎΠ²ΠΎΡ ΠΎΡ ΡΠΈΡΡΠ΅ΠΌΠΈΡΠ΅. Π ΡΠ°ΠΊΠ°Π²Π° ΡΠΈΡΡΠ°ΡΠΈΡ βΠ½ΠΎΡΠΌΠ°Π»Π½ΠΎΡΠΎβ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΈΡΠ°Π½Π΅, ΠΊΠΎΠ³Π°ΡΠΎ ΠΈΠΌΠ°ΠΌΠ΅ Π΅Π΄Π½Π° ΠΈΠ·ΠΏΡΠ»Π½ΡΠ²Π°ΡΠ° Π½ΠΈΡΠΊΠ°, Π²Π΅ΡΠ΅ Π½Π΅ Π΅ Π΅ΡΠ΅ΠΊΡΠΈΠ²Π½ΠΎ. Π’ΡΡΠ±Π²Π° ΠΏΠΎ Π½ΡΠΊΠ°ΠΊΡΠ² Π½Π°ΡΠΈΠ½ Π΄Π° ΡΠ°Π·ΡΠ΅ΡΠΈΠΌ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠ° Ρ Π΅Π΄Π½ΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½ΠΎΡΠΎ ΠΈΠ»ΠΈ ΠΏΠ°ΡΠ°Π»Π΅Π»Π½ΠΎ ΠΈΠ·ΠΏΡΠ»Π½Π΅Π½ΠΈΠ΅. ΠΡΠ²Π΅Π½ ΡΠΎΠ²Π° ΡΠΎΠ·ΠΈ ΠΏΡΠΎΠ±Π»Π΅ΠΌ ΡΡΡΠ΅ΡΡΠ²ΡΠ²Π° Π½Π° ΡΠ°Π·Π»ΠΈΡΠ½ΠΈ Π½ΠΈΠ²Π°: Π½Π° Π½ΠΈΠ²ΠΎ Π½ΠΈΡΠΊΠ°, Π½Π° Π½ΠΈΠ²ΠΎ ΠΏΡΠΎΡΠ΅Ρ, Π½Π° Π½ΠΈΠ²ΠΎ ΠΌΠ°ΡΠΈΠ½ΠΈ Π² ΠΌΡΠ΅ΠΆΠ°ΡΠ° (ΡΠ°Π·ΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈ ΡΠΈΡΡΠ΅ΠΌΠΈ). .NET ΠΈΠΌΠ° Π²ΠΈΡΠΎΠΊΠΎΠΊΠ°ΡΠ΅ΡΡΠ²Π΅Π½ΠΈ, ΠΈΠ·ΠΏΠΈΡΠ°Π½ΠΈ Π²ΡΠ² Π²ΡΠ΅ΠΌΠ΅ΡΠΎ ΡΠ΅Ρ Π½ΠΎΠ»ΠΎΠ³ΠΈΠΈ Π·Π° Π±ΡΡΠ·ΠΎ ΠΈ Π΅ΡΠ΅ΠΊΡΠΈΠ²Π½ΠΎ ΡΠ΅ΡΠ°Π²Π°Π½Π΅ Π½Π° ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΈ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠΈ.
ΠΠ°Π΄Π°ΡΠ°
ΠΠ΄ΡΠ³Π΅Ρ ΠΠ΅ΠΉΠΊΡΡΡΠ° Π·Π°Π΄Π°Π²Π° ΡΠΎΠ·ΠΈ ΠΏΡΠΎΠ±Π»Π΅ΠΌ Π½Π° ΡΠ²ΠΎΠΈΡΠ΅ ΡΡΠ΅Π½ΠΈΡΠΈ ΠΏΡΠ΅Π· 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
, Π½ΠΎ Ρ Π²ΡΡΠΊΠ°ΠΊΠ²ΠΈ ΡΠ΄ΠΎΠ±ΡΡΠ²Π°: Π²ΡΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ Π·Π° ΡΡΠ°ΡΡΠΈΡΠ°Π½Π΅ Π½Π° Π·Π°Π΄Π°ΡΠ° ΡΠ»Π΅Π΄ Π±Π»ΠΎΠΊ ΠΎΡ Π΄ΡΡΠ³ΠΈ Π·Π°Π΄Π°ΡΠΈ, Π²ΡΡΡΠ°Π½Π΅ΡΠΎ ΠΈΠΌ ΠΎΡ ΡΡΠ½ΠΊΡΠΈΠΈ, ΡΠ΄ΠΎΠ±Π½ΠΎΡΠΎ ΠΈΠΌ ΠΏΡΠ΅ΠΊΡΡΠ²Π°Π½Π΅ ΠΈ ΠΌΠ½ΠΎΠ³ΠΎ Π΄ΡΡΠ³ΠΈ. ΠΈ Ρ.Π½. Π’Π΅ ΡΠ° Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌΠΈ Π·Π° ΠΏΠΎΠ΄Π΄ΡΡΠΆΠ°Π½Π΅ Π½Π° ΠΊΠΎΠ½ΡΡΡΡΠΊΡΠΈΠΈ async/await (Π°ΡΠΈΠ½Ρ
ΡΠΎΠ½Π΅Π½ ΠΌΠΎΠ΄Π΅Π», Π±Π°Π·ΠΈΡΠ°Π½ Π½Π° Π·Π°Π΄Π°ΡΠΈ, ΡΠΈΠ½ΡΠ°ΠΊΡΠΈΡΠ½Π° Π·Π°Ρ
Π°Ρ Π·Π° ΠΈΠ·ΡΠ°ΠΊΠ²Π°Π½Π΅ Π½Π° 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.
ΠΠ° ΡΠ½ΠΈΠΌΠΊΠ°ΡΠ° Π±Π»ΠΎΠΊΠΈΡΠ°Π½Π΅ Π½Π° Π½ΠΈΡΠΊΠΈ (Π±Π΅Π·ΠΈΠ·Ρ ΠΎΠ΄ΠΈΡΠ°). ΠΠ΅Π»Π΅Π½ΠΎΡΠΎ ΠΏΠΎΠΊΠ°Π·Π²Π° ΠΈΠ·ΠΏΡΠ»Π½Π΅Π½ΠΈΠ΅, ΡΠ΅ΡΠ²Π΅Π½ΠΎΡΠΎ ΠΏΠΎΠΊΠ°Π·Π²Π° ΡΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·Π°ΡΠΈΡ, Π° ΡΠΈΠ²ΠΎΡΠΎ ΠΏΠΎΠΊΠ°Π·Π²Π°, ΡΠ΅ Π½ΠΈΡΠΊΠ°ΡΠ° ΡΠΏΠΈ. ΠΠΈΠ°ΠΌΠ°Π½ΡΠΈΡΠ΅ ΠΏΠΎΠΊΠ°Π·Π²Π°Ρ Π²ΡΠ΅ΠΌΠ΅ΡΠΎ Π·Π° ΡΡΠ°ΡΡΠΈΡΠ°Π½Π΅ Π½Π° Π·Π°Π΄Π°ΡΠΈΡΠ΅.
ΠΠ»Π°Π΄ΡΡ Π½Π° ΡΠΈΠ»ΠΎΡΠΎΡΠΈΡΠ΅
ΠΡΠΏΡΠ΅ΠΊΠΈ ΡΠ΅ Π½Π΅ ΡΠ΅ Π½ΡΠΆΠ΄Π°Π΅ΡΠ΅ ΠΎΡ ΠΌΠ½ΠΎΠ³ΠΎ Ρ ΡΠ°Π½Π°, Π·Π° Π΄Π° ΠΌΠΈΡΠ»ΠΈΡΠ΅, Π³Π»Π°Π΄ΡΡ ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΏΡΠΈΠ½ΡΠ΄ΠΈ Π²ΡΠ΅ΠΊΠΈ Π΄Π° ΡΠ΅ ΠΎΡΠΊΠ°ΠΆΠ΅ ΠΎΡ ΡΠΈΠ»ΠΎΡΠΎΡΠΈΡΡΠ°. ΠΠ΅ΠΊΠ° ΡΠ΅ ΠΎΠΏΠΈΡΠ°ΠΌΠ΅ Π΄Π° ΡΠΈΠΌΡΠ»ΠΈΡΠ°ΠΌΠ΅ ΡΠΈΡΡΠ°ΡΠΈΡΡΠ° Π½Π° Π³Π»Π°Π΄ΡΠ²Π°Π½Π΅ Π½Π° Π½ΠΈΡΠΊΠ° Π² Π½Π°ΡΠΈΡ ΠΏΡΠΎΠ±Π»Π΅ΠΌ. ΠΠ»Π°Π΄ΡΡ Π΅, ΠΊΠΎΠ³Π°ΡΠΎ Π΅Π΄Π½Π° Π½ΠΈΡΠΊΠ° ΡΠ°Π±ΠΎΡΠΈ, Π½ΠΎ Π±Π΅Π· Π·Π½Π°ΡΠΈΡΠ΅Π»Π½Π° ΡΠ°Π±ΠΎΡΠ°, Ρ Π΄ΡΡΠ³ΠΈ Π΄ΡΠΌΠΈ, ΡΠΎΠ²Π° Π΅ ΡΡΡΠ°ΡΠ° Π±Π΅Π·ΠΈΠ·Ρ ΠΎΠ΄ΠΈΡΠ°, ΡΠ°ΠΌΠΎ ΡΠ΅Π³Π° Π½ΠΈΡΠΊΠ°ΡΠ° Π½Π΅ ΡΠΏΠΈ, Π° Π°ΠΊΡΠΈΠ²Π½ΠΎ ΡΡΡΡΠΈ Π½Π΅ΡΠΎ Π·Π° ΡΠ΄Π΅Π½Π΅, Π½ΠΎ Π½ΡΠΌΠ° Ρ ΡΠ°Π½Π°. ΠΠ° Π΄Π° ΠΈΠ·Π±Π΅Π³Π½Π΅ΠΌ ΡΠ΅ΡΡΠΎ Π±Π»ΠΎΠΊΠΈΡΠ°Π½Π΅, ΡΠ΅ Π²ΡΡΠ½Π΅ΠΌ Π²ΠΈΠ»ΠΈΡΠ°ΡΠ° ΠΎΠ±ΡΠ°ΡΠ½ΠΎ, Π°ΠΊΠΎ Π½Π΅ ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° Π²Π·Π΅ΠΌΠ΅ΠΌ Π΄ΡΡΠ³Π°.
// Π’ΠΎ ΠΆΠ΅ ΡΡΠΎ ΠΈ Π² 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
{
// ΠΠ΄Π΅ΡΡ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ ΡΠΎΠ»ΡΠΊΠΎ ΠΎΠ΄ΠΈΠ½ ΠΏΠΎΡΠΎΠΊ (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 Π΅ Π»ΠΎΡΠΎ), ΡΡ ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Π·Π° ΡΠ»ΠΎΠΆΠ½ΠΈ ΠΏΡΠΎΠΌΠ΅Π½ΠΈ Π½Π° Π΅Π΄Π½Π° ΡΡΠΎΠΉΠ½ΠΎΡΡ (ΠΌΠΎΠ΄Π΅Π» Π·Π° Π±Π»ΠΎΠΊΠΈΡΠ°Π½Π΅ Π½Π° Π²ΡΠΈΡΠΊΠΎ).
Π Π΅ΡΠ΅Π½ΠΈΡ Π·Π° ΡΠ΅ΠΆΠΈΠΌ Π½Π° ΡΠ΄ΡΠΎΡΠΎ
ΠΠ° Π΄Π° ΠΈΠ·Π±Π΅Π³Π½Π΅ΠΌ Π·Π°Π³ΡΠ±Π°ΡΠ° Π½Π° ΡΠ΅ΡΡΡΡΠΈ Π² ΡΠΈΠΊΡΠ», Π½Π΅ΠΊΠ° ΡΠ°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ ΠΊΠ°ΠΊ Π΄Π° Π±Π»ΠΎΠΊΠΈΡΠ°ΠΌΠ΅ Π½ΠΈΡΠΊΠ°. Π‘ Π΄ΡΡΠ³ΠΈ Π΄ΡΠΌΠΈ, ΠΏΡΠΎΠ΄ΡΠ»ΠΆΠ°Π²Π°ΠΉΠΊΠΈ Π½Π°ΡΠΈΡ ΠΏΡΠΈΠΌΠ΅Ρ, Π½Π΅ΠΊΠ° Π²ΠΈΠ΄ΠΈΠΌ ΠΊΠ°ΠΊ ΡΠ΅ΡΠ²ΠΈΡΡΠΎΡΡΡ ΠΏΡΠΈΡΠΏΠΈΠ²Π° ΡΠΈΠ»ΠΎΡΠΎΡΠ° ΠΈ Π³ΠΎ ΡΡΠ±ΡΠΆΠ΄Π° ΡΠ°ΠΌΠΎ ΠΊΠΎΠ³Π°ΡΠΎ Π΅ Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌΠΎ. ΠΡΡΠ²ΠΎ, Π½Π΅ΠΊΠ° Π΄Π° ΡΠ°Π·Π³Π»Π΅Π΄Π°ΠΌΠ΅ ΠΊΠ°ΠΊ Π΄Π° Π½Π°ΠΏΡΠ°Π²ΠΈΡΠ΅ ΡΠΎΠ²Π° ΡΡΠ΅Π· ΡΠ΅ΠΆΠΈΠΌΠ° Π½Π° ΡΠ΄ΡΠΎΡΠΎ Π½Π° ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΎΠ½Π½Π°ΡΠ° ΡΠΈΡΡΠ΅ΠΌΠ°. ΠΡΠΈΡΠΊΠΈ ΡΡΡΡΠΊΡΡΡΠΈ ΡΠ°ΠΌ ΡΠ΅ΡΡΠΎ ΡΠ΅ ΠΎΠΊΠ°Π·Π²Π°Ρ ΠΏΠΎ-Π±Π°Π²Π½ΠΈ ΠΎΡ ΡΠ΅Π·ΠΈ Π² ΠΏΠΎΡΡΠ΅Π±ΠΈΡΠ΅Π»ΡΠΊΠΎΡΠΎ ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ²ΠΎ. ΠΡΠΊΠΎΠ»ΠΊΠΎ ΠΏΡΡΠΈ ΠΏΠΎ-Π±Π°Π²Π½ΠΎ, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ AutoResetEvent
ΠΌΠΎΠΆΠ΅ Π±ΠΈ 53 ΠΏΡΡΠΈ ΠΏΠΎ-Π±Π°Π²Π½ΠΎ SpinLock
[Π ΠΈΡ
ΡΠ΅Ρ]. ΠΠΎ Ρ ΡΡΡ
Π½Π° ΠΏΠΎΠΌΠΎΡ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΡΠΈΠ½Ρ
ΡΠΎΠ½ΠΈΠ·ΠΈΡΠ°ΡΠ΅ ΠΏΡΠΎΡΠ΅ΡΠΈΡΠ΅ Π² ΡΡΠ»Π°ΡΠ° ΡΠΈΡΡΠ΅ΠΌΠ°, ΡΠΏΡΠ°Π²Π»ΡΠ²Π°Π½ΠΈ ΠΈΠ»ΠΈ Π½Π΅.
ΠΡΠ½ΠΎΠ²Π½ΠΈΡΡ Π΄ΠΈΠ·Π°ΠΉΠ½ ΡΡΠΊ Π΅ ΡΠ΅ΠΌΠ°ΡΠΎΡ, ΠΏΡΠ΅Π΄Π»ΠΎΠΆΠ΅Π½ ΠΎΡ ΠΠ΅ΠΉΠΊΡΡΡΠ° ΠΏΡΠ΅Π΄ΠΈ ΠΏΠΎΠ²Π΅ΡΠ΅ ΠΎΡ ΠΏΠΎΠ»ΠΎΠ²ΠΈΠ½ Π²Π΅ΠΊ. Π‘Π΅ΠΌΠ°ΡΠΎΡΡΡ Π΅, Π½Π°ΠΉ-ΠΏΡΠΎΡΡΠΎ ΠΊΠ°Π·Π°Π½ΠΎ, ΠΏΠΎΠ»ΠΎΠΆΠΈΡΠ΅Π»Π½ΠΎ ΡΡΠ»ΠΎ ΡΠΈΡΠ»ΠΎ, ΡΠΏΡΠ°Π²Π»ΡΠ²Π°Π½ΠΎ ΠΎΡ ΡΠΈΡΡΠ΅ΠΌΠ°ΡΠ°, ΠΈ Π΄Π²Π΅ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ Π²ΡΡΡ
Ρ Π½Π΅Π³ΠΎ - ΡΠ²Π΅Π»ΠΈΡΠ°Π²Π°Π½Π΅ ΠΈ Π½Π°ΠΌΠ°Π»ΡΠ²Π°Π½Π΅. ΠΠΊΠΎ Π½Π΅ Π΅ Π²ΡΠ·ΠΌΠΎΠΆΠ½ΠΎ Π΄Π° ΡΠ΅ Π½Π°ΠΌΠ°Π»ΠΈ Π½ΡΠ»Π°ΡΠ°, ΡΠΎΠ³Π°Π²Π° ΠΈΠ·Π²ΠΈΠΊΠ²Π°ΡΠ°ΡΠ° Π½ΠΈΡΠΊΠ° ΡΠ΅ Π±Π»ΠΎΠΊΠΈΡΠ°. ΠΠΎΠ³Π°ΡΠΎ Π±ΡΠΎΡΡ ΡΠ΅ ΡΠ²Π΅Π»ΠΈΡΠΈ ΠΎΡ Π΄ΡΡΠ³Π° Π°ΠΊΡΠΈΠ²Π½Π° Π½ΠΈΡΠΊΠ°/ΠΏΡΠΎΡΠ΅Ρ, ΡΠΎΠ³Π°Π²Π° Π½ΠΈΡΠΊΠΈΡΠ΅ ΡΠ΅ ΠΏΡΠ΅Π΄Π°Π²Π°Ρ ΠΈ ΡΠ΅ΠΌΠ°ΡΠΎΡΡΡ ΠΎΡΠ½ΠΎΠ²ΠΎ ΡΠ΅ Π½Π°ΠΌΠ°Π»ΡΠ²Π° Ρ ΠΏΡΠ΅Π΄Π°Π΄Π΅Π½ΠΈΡ Π±ΡΠΎΠΉ. ΠΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΡΠΈ ΠΏΡΠ΅Π΄ΡΡΠ°Π²ΠΈΡΠ΅ Π²Π»Π°ΠΊΠΎΠ²Π΅ Π² ΡΡΡΠ½ΠΎ ΠΌΡΡΡΠΎ ΡΡΡ ΡΠ΅ΠΌΠ°ΡΠΎΡ. .NET ΠΏΡΠ΅Π΄Π»Π°Π³Π° Π½ΡΠΊΠΎΠ»ΠΊΠΎ ΠΊΠΎΠ½ΡΡΡΡΠΊΡΠΈΠΈ Ρ ΠΏΠΎΠ΄ΠΎΠ±Π½Π° ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π»Π½ΠΎΡΡ: AutoResetEvent
, ManualResetEvent
, Mutex
ΠΈ ΡΠ΅Π±Π΅ ΡΠΈ Semaphore
. Π©Π΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ AutoResetEvent
, ΡΠΎΠ²Π° Π΅ Π½Π°ΠΉ-ΠΏΡΠΎΡΡΠ°ΡΠ° ΠΎΡ ΡΠ΅Π·ΠΈ ΠΊΠΎΠ½ΡΡΡΡΠΊΡΠΈΠΈ: ΡΠ°ΠΌΠΎ Π΄Π²Π΅ ΡΡΠΎΠΉΠ½ΠΎΡΡΠΈ 0 ΠΈ 1 (false, true). ΠΠ΅ΠΉΠ½ΠΈΡΡ ΠΌΠ΅ΡΠΎΠ΄ 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
), ΠΊΠΎΠΈΡΠΎ ΠΏΡΠΈΡΡΡΡΠ²Π°Ρ Π²ΡΠ² Π²ΡΠΈΡΠΊΠΈ ΠΎΠ±Π΅ΠΊΡΠΈ. Π‘Π»Π΅Π΄ΠΎΠ²Π°ΡΠ΅Π»Π½ΠΎ, Π°ΠΊΠΎ Π΅ ΠΈΠ·Π±ΡΠ°Π½ Π½Π΅ΠΏΠΎΠ΄Ρ
ΠΎΠ΄ΡΡ ΠΎΠ±Π΅ΠΊΡ, ΠΌΠΎΠΆΠ΅ΡΠ΅ Π»Π΅ΡΠ½ΠΎ Π΄Π° ΠΏΠΎΠ»ΡΡΠΈΡΠ΅ Π±Π»ΠΎΠΊΠΈΡΠ°Π½Π΅ (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, Π°ΠΊΠΎ Π·Π°ΠΊΠ»ΡΡΠΈΡΠ΅ ΠΈΠ½ΡΠ΅ΡΠ½ΠΈΡΠ°Π½ Π½ΠΈΠ·). ΠΠΈΠ½Π°Π³ΠΈ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ ΡΠΊΡΠΈΡ ΠΏΡΠ΅Π΄ΠΌΠ΅Ρ Π·Π° ΡΠΎΠ²Π°.
ΠΠΎΠ΄Π΅Π»ΡΡ Condition Variable Π²ΠΈ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ²Π° ΠΏΠΎ-ΡΠ±ΠΈΡΠΎ Π΄Π° ΠΏΡΠΈΠ»ΠΎΠΆΠΈΡΠ΅ ΠΎΡΠ°ΠΊΠ²Π°Π½Π΅ΡΠΎ Π½Π° Π½ΡΠΊΠ°ΠΊΠ²ΠΎ ΡΠ»ΠΎΠΆΠ½ΠΎ ΡΡΠ»ΠΎΠ²ΠΈΠ΅. Π .NET Π΅ Π½Π΅ΠΏΡΠ»Π½ΠΎ ΡΠΏΠΎΡΠ΅Π΄ ΠΌΠ΅Π½, Π·Π°ΡΠΎΡΠΎ... ΠΠ° ΡΠ΅ΠΎΡΠΈΡ ΡΡΡΠ±Π²Π° Π΄Π° ΠΈΠΌΠ° Π½ΡΠΊΠΎΠ»ΠΊΠΎ ΠΎΠΏΠ°ΡΠΊΠΈ Π·Π° Π½ΡΠΊΠΎΠ»ΠΊΠΎ ΠΏΡΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈ (ΠΊΠ°ΠΊΡΠΎ Π² Posix Threads), Π° Π½Π΅ Π·Π° Π΅Π΄Π½ΠΎ Π·Π°ΠΊΠ»ΡΡΠ²Π°Π½Π΅. Π’ΠΎΠ³Π°Π²Π° Π±ΠΈ Π±ΠΈΠ»ΠΎ Π²ΡΠ·ΠΌΠΎΠΆΠ½ΠΎ Π΄Π° Π³ΠΈ Π½Π°ΠΏΡΠ°Π²ΠΈΠΌ Π·Π° Π²ΡΠΈΡΠΊΠΈ ΡΠΈΠ»ΠΎΡΠΎΡΠΈ. ΠΠΎ Π΄ΠΎΡΠΈ ΠΈ Π² ΡΠ°Π·ΠΈ ΡΠΎΡΠΌΠ° Π²ΠΈ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ²Π° Π΄Π° ΡΡΠΊΡΠ°ΡΠΈΡΠ΅ ΠΊΠΎΠ΄Π°.
ΠΠ½ΠΎΠ³ΠΎ ΡΠΈΠ»ΠΎΡΠΎΡΠΈ ΠΈΠ»ΠΈ async
/ await
ΠΠΎΠ±ΡΠ΅, ΡΠ΅Π³Π° ΠΌΠΎΠΆΠ΅ΠΌ Π΅ΡΠ΅ΠΊΡΠΈΠ²Π½ΠΎ Π΄Π° Π±Π»ΠΎΠΊΠΈΡΠ°ΠΌΠ΅ ΡΠ΅ΠΌΠΈ. ΠΠΎ ΠΊΠ°ΠΊΠ²ΠΎ ΡΠ΅ ΡΡΠ°Π½Π΅, Π°ΠΊΠΎ ΠΈΠΌΠ°ΠΌΠ΅ ΠΌΠ½ΠΎΠ³ΠΎ ΡΠΈΠ»ΠΎΡΠΎΡΠΈ? 100? 10000 100000? ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΏΠΎΠ»ΡΡΠΈΡ ΠΌΠ΅ 4 XNUMX Π·Π°ΡΠ²ΠΊΠΈ ΠΊΡΠΌ ΡΠ΅Π± ΡΡΡΠ²ΡΡΠ°. Π‘ΡΠ·Π΄Π°Π²Π°Π½Π΅ΡΠΎ Π½Π° Π½ΠΈΡΠΊΠ° Π·Π° Π²ΡΡΠΊΠ° Π·Π°ΡΠ²ΠΊΠ° ΡΠ΅ Π±ΡΠ΄Π΅ ΡΠΊΡΠΏΠΎ, Π·Π°ΡΠΎΡΠΎ ΡΠΎΠ»ΠΊΠΎΠ²Π° ΠΌΠ½ΠΎΠ³ΠΎ Π½ΠΈΡΠΊΠΈ Π½ΡΠΌΠ° Π΄Π° Π±ΡΠ΄Π°Ρ ΠΈΠ·ΠΏΡΠ»Π½Π΅Π½ΠΈ ΠΏΠ°ΡΠ°Π»Π΅Π»Π½ΠΎ. Π‘Π°ΠΌΠΎ ΡΠΎΠ»ΠΊΠΎΠ²Π° Π»ΠΎΠ³ΠΈΡΠ΅ΡΠΊΠΈ ΡΠ΄ΡΠ° ΡΠ΅ Π±ΡΠ΄Π°Ρ ΠΈΠ·ΠΏΡΠ»Π½Π΅Π½ΠΈ (ΠΈΠΌΠ°ΠΌ XNUMX). Π Π²ΡΠΈΡΠΊΠΈ ΠΎΡΡΠ°Π½Π°Π»ΠΈ ΠΏΡΠΎΡΡΠΎ ΡΠ΅ ΠΎΡΠ½Π΅ΠΌΠ°Ρ ΡΠ΅ΡΡΡΡΠΈ. ΠΠ΄Π½ΠΎ ΡΠ΅ΡΠ΅Π½ΠΈΠ΅ Π½Π° ΡΠΎΠ·ΠΈ ΠΏΡΠΎΠ±Π»Π΅ΠΌ Π΅ ΠΌΠΎΠ΄Π΅Π»ΡΡ 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();
}
ΠΠ΅ΡΠΎΠ΄ Ρ async
/ await
ΡΠ΅ ΠΏΡΠ΅Π²Π΅ΠΆΠ΄Π° Π² Ρ
ΠΈΡΡΡ ΠΊΡΠ°Π΅Π½ Π°Π²ΡΠΎΠΌΠ°Ρ, ΠΊΠΎΠΉΡΠΎ Π½Π΅Π·Π°Π±Π°Π²Π½ΠΎ Π²ΡΡΡΠ° Π²ΡΡΡΠ΅ΡΠ½ΠΈΡ ΡΠΈ Task
. Π§ΡΠ΅Π· Π½Π΅Π³ΠΎ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΠΈΠ·ΡΠ°ΠΊΠ°ΡΠ΅ ΠΌΠ΅ΡΠΎΠ΄Π° Π΄Π° Π·Π°Π²ΡΡΡΠΈ, Π΄Π° Π³ΠΎ ΠΎΡΠΌΠ΅Π½ΠΈΡΠ΅ ΠΈ Π²ΡΠΈΡΠΊΠΎ ΠΎΡΡΠ°Π½Π°Π»ΠΎ, ΠΊΠΎΠ΅ΡΠΎ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° Π½Π°ΠΏΡΠ°Π²ΠΈΡΠ΅ Ρ Task. ΠΡΡΡΠ΅ Π² ΠΌΠ΅ΡΠΎΠ΄Π° Π΄ΡΡΠΆΠ°Π²Π½Π° ΠΌΠ°ΡΠΈΠ½Π° ΠΊΠΎΠ½ΡΡΠΎΠ»ΠΈΡΠ° ΠΈΠ·ΠΏΡΠ»Π½Π΅Π½ΠΈΠ΅ΡΠΎ. ΠΠ·Π²ΠΎΠ΄ΡΡ Π΅, ΡΠ΅ Π°ΠΊΠΎ Π½ΡΠΌΠ° Π·Π°Π±Π°Π²ΡΠ½Π΅, ΡΠΎΠ³Π°Π²Π° ΠΈΠ·ΠΏΡΠ»Π½Π΅Π½ΠΈΠ΅ΡΠΎ Π΅ ΡΠΈΠ½Ρ
ΡΠΎΠ½Π½ΠΎ ΠΈ Π°ΠΊΠΎ ΠΈΠΌΠ°, ΡΠΎΠ³Π°Π²Π° Π½ΠΈΡΠΊΠ°ΡΠ° ΡΠ΅ ΠΎΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π°Π²Π°. ΠΠ° ΠΏΠΎ-Π΄ΠΎΠ±ΡΠΎ ΡΠ°Π·Π±ΠΈΡΠ°Π½Π΅ Π½Π° ΡΠΎΠ²Π° Π΅ ΠΏΠΎ-Π΄ΠΎΠ±ΡΠ΅ Π΄Π° ΠΏΠΎΠ³Π»Π΅Π΄Π½Π΅ΡΠ΅ ΡΠ°Π·ΠΈ Π΄ΡΡΠΆΠ°Π²Π½Π° ΠΌΠ°ΡΠΈΠ½Π°. ΠΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΡΡΠ·Π΄Π°Π²Π°ΡΠ΅ Π²Π΅ΡΠΈΠ³ΠΈ ΠΎΡ ΡΡΡ
async
/ await
ΠΌΠ΅ΡΠΎΠ΄ΠΈ.
ΠΠ΅ΠΊΠ° Π³ΠΎ ΡΠ΅ΡΡΠ²Π°ΠΌΠ΅. Π Π°Π±ΠΎΡΠ° Π½Π° 100 ΡΠΈΠ»ΠΎΡΠΎΡΠ° Π½Π° ΠΌΠ°ΡΠΈΠ½Π° Ρ 4 Π»ΠΎΠ³ΠΈΡΠ΅ΡΠΊΠΈ ΡΠ΄ΡΠ°, 8 ΡΠ΅ΠΊΡΠ½Π΄ΠΈ. ΠΡΠ΅Π΄ΠΈΡΠ½ΠΎΡΠΎ ΡΠ΅ΡΠ΅Π½ΠΈΠ΅ Ρ Monitor ΠΈΠ·ΠΏΡΠ»Π½ΠΈ ΡΠ°ΠΌΠΎ ΠΏΡΡΠ²ΠΈΡΠ΅ 4 Π½ΠΈΡΠΊΠΈ ΠΈ ΠΈΠ·ΠΎΠ±ΡΠΎ Π½Π΅ ΠΈΠ·ΠΏΡΠ»Π½ΠΈ ΠΎΡΡΠ°Π½Π°Π»ΠΈΡΠ΅. ΠΡΡΠΊΠ° ΠΎΡ ΡΠ΅Π·ΠΈ 4 Π½ΠΈΡΠΊΠΈ Π±Π΅ΡΠ΅ Π½Π΅Π°ΠΊΡΠΈΠ²Π½Π° Π·Π° ΠΎΠΊΠΎΠ»ΠΎ 2ms. Π ΡΠ΅ΡΠ΅Π½ΠΈΠ΅ΡΠΎ async/await ΠΈΠ·ΠΏΡΠ»Π½ΠΈ Π²ΡΠΈΡΠΊΠΈΡΠ΅ 100, ΡΡΡ ΡΡΠ΅Π΄Π½ΠΎ 6.8 ΡΠ΅ΠΊΡΠ½Π΄ΠΈ Π²ΡΡΠΊΠΎ ΠΈΠ·ΡΠ°ΠΊΠ²Π°Π½Π΅. Π Π°Π·Π±ΠΈΡΠ° ΡΠ΅, Π² ΡΠ΅Π°Π»Π½ΠΈ ΡΠΈΡΡΠ΅ΠΌΠΈ Π±Π΅Π·Π΄Π΅ΠΉΡΡΠ²ΠΈΠ΅ΡΠΎ Π·Π° 6 ΡΠ΅ΠΊΡΠ½Π΄ΠΈ Π΅ Π½Π΅Π΄ΠΎΠΏΡΡΡΠΈΠΌΠΎ ΠΈ Π΅ ΠΏΠΎ-Π΄ΠΎΠ±ΡΠ΅ Π΄Π° Π½Π΅ ΠΎΠ±ΡΠ°Π±ΠΎΡΠ²Π°ΡΠ΅ ΡΠΎΠ»ΠΊΠΎΠ²Π° ΠΌΠ½ΠΎΠ³ΠΎ Π·Π°ΡΠ²ΠΊΠΈ ΠΏΠΎ ΡΠΎΠ·ΠΈ Π½Π°ΡΠΈΠ½. Π Π΅ΡΠ΅Π½ΠΈΠ΅ΡΠΎ Ρ ΠΠΎΠ½ΠΈΡΠΎΡ ΡΠ΅ ΠΎΠΊΠ°Π·Π° Π½ΠΈΠΊΠ°ΠΊ Π½Π΅ ΠΌΠ°ΡΠ°Π±ΠΈΡΡΠ΅ΠΌΠΎ.
ΠΠ°ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅
ΠΠ°ΠΊΡΠΎ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° Π²ΠΈΠ΄ΠΈΡΠ΅ ΠΎΡ ΡΠ΅Π·ΠΈ ΠΌΠ°Π»ΠΊΠΈ ΠΏΡΠΈΠΌΠ΅ΡΠΈ, .NET ΠΏΠΎΠ΄Π΄ΡΡΠΆΠ° ΠΌΠ½ΠΎΠ³ΠΎ ΠΊΠΎΠ½ΡΡΡΡΠΊΡΠΈΠΈ Π·Π° ΡΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·Π°ΡΠΈΡ. ΠΡΠΏΡΠ΅ΠΊΠΈ ΡΠΎΠ²Π°, Π½Π΅ Π²ΠΈΠ½Π°Π³ΠΈ Π΅ ΠΎΡΠ΅Π²ΠΈΠ΄Π½ΠΎ ΠΊΠ°ΠΊ Π΄Π° Π³ΠΈ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΡΠ΅. ΠΠ°Π΄ΡΠ²Π°ΠΌ ΡΠ΅ ΡΠ°Π·ΠΈ ΡΡΠ°ΡΠΈΡ Π΄Π° Π΅ Π±ΠΈΠ»Π° ΠΏΠΎΠ»Π΅Π·Π½Π°. ΠΠ° ΠΌΠΎΠΌΠ΅Π½ΡΠ° ΠΏΡΠΈΠΊΠ»ΡΡΠ²Π°ΠΌΠ΅, Π½ΠΎ Π²ΡΠ΅ ΠΎΡΠ΅ ΠΈΠΌΠ° ΠΌΠ½ΠΎΠ³ΠΎ ΠΈΠ½ΡΠ΅ΡΠ΅ΡΠ½ΠΈ Π½Π΅ΡΠ°, ΠΊΠ°ΡΠΎ ΠΊΠΎΠ»Π΅ΠΊΡΠΈΠΈ, Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΈ Π·Π° Π½ΠΈΡΠΊΠΈ, TPL ΠΏΠΎΡΠΎΠΊ ΠΎΡ Π΄Π°Π½Π½ΠΈ, ΡΠ΅Π°ΠΊΡΠΈΠ²Π½ΠΎ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΈΡΠ°Π½Π΅, ΠΌΠΎΠ΄Π΅Π» Π½Π° ΡΠΎΡΡΡΠ΅ΡΠ½ΠΈ ΡΡΠ°Π½Π·Π°ΠΊΡΠΈΠΈ ΠΈ Ρ.Π½.
ΠΈΠ·ΡΠΎΡΠ½ΠΈΡΠΈ
- ΠΠΈΠ·ΡΠ°Π»ΠΈΠ·Π°ΡΠΈΡ Π½Π° ΠΏΠΎΡΠΎΠΊΠ°:
ΠΠΈΠ·ΡΠ°Π»ΠΈΠ·Π°ΡΠΎΡ Π½Π° Π΅Π΄Π½ΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½ΠΎΡΡ - MSDN:
Threading ,ΠΠΎΠ΄Π΅Π»ΠΈ Π½Π° Π°ΡΠΈΠ½Ρ ΡΠΎΠ½Π½ΠΎ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΈΡΠ°Π½Π΅ ΠΈ ΠΌΠ½ΠΎΠ³ΠΎ Π΄ΡΡΠ³ΠΈ Π΄ΡΡΠ³ - [Π ΠΈΡ ΡΠ΅Ρ] β CLR ΡΡΠ΅Π· C#, ΠΠΆΠ΅ΡΡΠΈ Π ΠΈΡ ΡΠ΅Ρ
- [ΠΡΠΈΠΊ ΠΠΈΠΏΠ΅ΡΡ] -
ΠΡΠ½ΠΎΡΠ½ΠΎ ΠΊΠ»ΡΡΠ°Π»ΠΊΠ°ΡΠ° ΠΠ·Ρ ΠΎΠ΄Π΅Π½ ΠΊΠΎΠ΄ - ΠΠ°ΡΡΠΈΠ½Π° β βΠ’Π°Π½Ρ ΡΡΠ΅Π΄ ΠΌΠ΅ΡΠΎΠ²Π΅ΡΠ΅β, Π. Π‘Π΅ΠΌΠΈΡΠ°Π΄ΡΠΊΠΈ
ΠΠ·ΡΠΎΡΠ½ΠΈΠΊ: www.habr.com