ΠΡΠ΄Π΅ Π΄Π° Π²ΠΈΠ΄ΠΈΠΌΠ΅ ΠΊΠ°ΠΊΠΎ ΡΡΠ½ΠΊΡΠΈΠΎΠ½ΠΈΡΠ° ΠΈΡΡΠΎΠ²ΡΠ΅ΠΌΠ΅Π½ΠΎΡΠΎ ΠΈ ΠΏΠ°ΡΠ°Π»Π΅Π»Π½ΠΎΡΠΎ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΈΡΠ°ΡΠ΅ Π²ΠΎ .Net, ΠΊΠΎΡΠΈΡΡΠ΅ΡΡΠΈ Π³ΠΎ ΠΊΠ°ΠΊΠΎ ΠΏΡΠΈΠΌΠ΅Ρ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠΎΡ ΡΠΎ ΡΠ°Π΄Π΅ΡΠ΅ Π½Π° Π€ΠΈΠ»ΠΎΠ·ΠΎΡΠΈ. ΠΠ»Π°Π½ΠΎΡ Π΅ ΠΎΠ²ΠΎΡ, ΠΎΠ΄ ΡΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·Π°ΡΠΈΡΠ° Π½Π° Π½ΠΈΡΠΊΠΈ/ΠΏΡΠΎΡΠ΅ΡΠΈ, Π΄ΠΎ ΠΌΠΎΠ΄Π΅Π» Π½Π° Π°ΠΊΡΠ΅Ρ (Π²ΠΎ ΡΠ»Π΅Π΄Π½ΠΈΡΠ΅ Π΄Π΅Π»ΠΎΠ²ΠΈ). Π‘ΡΠ°ΡΠΈΡΠ°ΡΠ° ΠΌΠΎΠΆΠ΅ Π΄Π° Π±ΠΈΠ΄Π΅ ΠΊΠΎΡΠΈΡΠ½Π° Π·Π° ΠΏΡΠ²ΠΎΡΠΎ Π·Π°ΠΏΠΎΠ·Π½Π°Π²Π°ΡΠ΅ ΠΈΠ»ΠΈ Π·Π° Π΄Π° Π³ΠΎ ΠΎΡΠ²Π΅ΠΆΠΈΡΠ΅ Π²Π°ΡΠ΅ΡΠΎ Π·Π½Π°Π΅ΡΠ΅.
ΠΠΎΡΡΠΎ Π²ΠΎΠΎΠΏΡΡΠΎ Π΄Π° Π³ΠΎ Π½Π°ΠΏΡΠ°Π²ΠΈ ΡΠΎΠ°? Π’ΡΠ°Π½Π·ΠΈΡΡΠΎΡΠΈΡΠ΅ ΡΠ° Π΄ΠΎΡΡΠΈΠ³Π½ΡΠ²Π°Π°Ρ ΡΠ²ΠΎΡΠ°ΡΠ° ΠΌΠΈΠ½ΠΈΠΌΠ°Π»Π½Π° Π³ΠΎΠ»Π΅ΠΌΠΈΠ½Π°, ΠΡΡΠΎΠ²ΠΈΠΎΡ Π·Π°ΠΊΠΎΠ½ ΡΠ΅ ΠΏΠΎΡΠΏΠΈΡΠ° Π½Π° ΠΎΠ³ΡΠ°Π½ΠΈΡΡΠ²Π°ΡΠ΅ΡΠΎ Π½Π° Π±ΡΠ·ΠΈΠ½Π°ΡΠ° Π½Π° ΡΠ²Π΅ΡΠ»ΠΈΠ½Π°ΡΠ° ΠΈ Π·Π°ΡΠΎΠ° ΡΠ΅ Π·Π°Π±Π΅Π»Π΅ΠΆΡΠ²Π° Π·Π³ΠΎΠ»Π΅ΠΌΡΠ²Π°ΡΠ΅ Π½Π° Π±ΡΠΎΡΠΎΡ, ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ΅ Π½Π°ΠΏΡΠ°Π²Π°Ρ ΠΏΠΎΠ²Π΅ΡΠ΅ ΡΡΠ°Π½Π·ΠΈΡΡΠΎΡΠΈ. ΠΠΎ ΠΈΡΡΠΎ Π²ΡΠ΅ΠΌΠ΅, ΠΊΠΎΠ»ΠΈΡΠΈΠ½Π°ΡΠ° Π½Π° ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ ΡΠ°ΡΡΠ΅, Π° ΠΊΠΎΡΠΈΡΠ½ΠΈΡΠΈΡΠ΅ ΠΎΡΠ΅ΠΊΡΠ²Π°Π°Ρ ΠΈΡΠ΅Π½ ΠΎΠ΄Π³ΠΎΠ²ΠΎΡ ΠΎΠ΄ ΡΠΈΡΡΠ΅ΠΌΠΈΡΠ΅. ΠΠΎ ΡΠ°ΠΊΠ²Π° ΡΠΈΡΡΠ°ΡΠΈΡΠ°, βΠ½ΠΎΡΠΌΠ°Π»Π½ΠΎΡΠΎβ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΈΡΠ°ΡΠ΅, ΠΊΠΎΠ³Π° ΠΈΠΌΠ°ΠΌΠ΅ Π΅Π΄Π½Π° Π½ΠΈΡΠΊΠ° Π·Π° ΠΈΠ·Π²ΡΡΡΠ²Π°ΡΠ΅, Π²Π΅ΡΠ΅ Π½Π΅ Π΅ Π΅ΡΠ΅ΠΊΡΠΈΠ²Π½ΠΎ. Π’ΡΠ΅Π±Π° Π½Π΅ΠΊΠ°ΠΊΠΎ Π΄Π° Π³ΠΎ ΡΠ΅ΡΠΈΡΠ΅ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠΎΡ ΡΠΎ ΠΈΡΡΠΎΠ²ΡΠ΅ΠΌΠ΅Π½ΠΎ ΠΈΠ»ΠΈ ΠΈΡΡΠΎΠ²ΡΠ΅ΠΌΠ΅Π½ΠΎ ΠΈΠ·Π²ΡΡΡΠ²Π°ΡΠ΅. ΠΠΎΠΊΡΠ°Ρ ΡΠΎΠ°, ΠΎΠ²ΠΎΡ ΠΏΡΠΎΠ±Π»Π΅ΠΌ ΠΏΠΎΡΡΠΎΠΈ Π½Π° ΡΠ°Π·Π»ΠΈΡΠ½ΠΈ Π½ΠΈΠ²ΠΎΠ°: Π½Π° Π½ΠΈΠ²ΠΎ Π½Π° Π½ΠΈΡΠΊΠΈ, Π½Π° Π½ΠΈΠ²ΠΎ Π½Π° ΠΏΡΠΎΡΠ΅ΡΠΈ, Π½Π° Π½ΠΈΠ²ΠΎ Π½Π° ΠΌΠ°ΡΠΈΠ½ΠΈ Π²ΠΎ ΠΌΡΠ΅ΠΆΠ°ΡΠ° (Π΄ΠΈΡΡΡΠΈΠ±ΡΠΈΡΠ°Π½ΠΈ ΡΠΈΡΡΠ΅ΠΌΠΈ). .NET ΠΈΠΌΠ° Π²ΠΈΡΠΎΠΊΠΎΠΊΠ²Π°Π»ΠΈΡΠ΅ΡΠ½ΠΈ, Π²ΡΠ΅ΠΌΠ΅Π½ΡΠΊΠΈ ΡΠ΅ΡΡΠΈΡΠ°Π½ΠΈ ΡΠ΅Ρ Π½ΠΎΠ»ΠΎΠ³ΠΈΠΈ Π·Π° Π±ΡΠ·ΠΎ ΠΈ Π΅ΡΠΈΠΊΠ°ΡΠ½ΠΎ ΡΠ΅ΡΠ°Π²Π°ΡΠ΅ Π½Π° Π²Π°ΠΊΠ²ΠΈΡΠ΅ ΠΏΡΠΎΠ±Π»Π΅ΠΌΠΈ.
ΠΠ°Π΄Π°ΡΠ°
ΠΠ΄ΡΠ³Π΅Ρ ΠΠΈΡΠΊΡΡΡΠ° ΠΈΠΌ Π³ΠΎ ΠΏΠΎΡΡΠ°Π²ΠΈ ΠΎΠ²ΠΎΡ ΠΏΡΠΎΠ±Π»Π΅ΠΌ Π½Π° ΡΠ²ΠΎΠΈΡΠ΅ ΡΡΡΠ΄Π΅Π½ΡΠΈ ΡΡΡΠ΅ Π²ΠΎ 1965 Π³ΠΎΠ΄ΠΈΠ½Π°. ΠΠΎΡΠΏΠΎΡΡΠ°Π²Π΅Π½Π°ΡΠ° ΡΠΎΡΠΌΡΠ»Π°ΡΠΈΡΠ° Π΅ ΡΠ»Π΅Π΄Π½Π°. ΠΠΌΠ° ΠΎΠ΄ΡΠ΅Π΄Π΅Π½ (ΠΎΠ±ΠΈΡΠ½ΠΎ ΠΏΠ΅Ρ) Π±ΡΠΎΡ Π½Π° ΡΠΈΠ»ΠΎΠ·ΠΎΡΠΈ ΠΈ ΠΈΡΡΠΎ ΡΠΎΠ»ΠΊΡ Π²ΠΈΠ»ΡΡΠΊΠΈ. Π’ΠΈΠ΅ ΡΠ΅Π΄Π°Ρ Π½Π° ΡΡΠΊΠ°Π»Π΅Π·Π½Π° ΠΌΠ°ΡΠ°, ΡΠΎ Π²ΠΈΠ»ΡΡΠΊΠΈ ΠΌΠ΅ΡΡ Π½ΠΈΠ². Π€ΠΈΠ»ΠΎΠ·ΠΎΡΠΈΡΠ΅ ΠΌΠΎΠΆΠ°Ρ Π΄Π° ΡΠ°Π΄Π°Ρ ΠΎΠ΄ ΡΠ²ΠΎΠΈΡΠ΅ ΡΠΈΠ½ΠΈΠΈ ΡΠΎ Π±Π΅ΡΠΊΡΠ°ΡΠ½Π° Ρ ΡΠ°Π½Π°, Π΄Π° ΡΠ°Π·ΠΌΠΈΡΠ»ΡΠ²Π°Π°Ρ ΠΈΠ»ΠΈ Π΄Π° ΡΠ΅ΠΊΠ°Π°Ρ. ΠΠ° Π΄Π° ΡΠ°Π΄Π΅ΡΠ΅ ΡΠΈΠ»ΠΎΠ·ΠΎΡ, ΡΡΠ΅Π±Π° Π΄Π° Π·Π΅ΠΌΠ΅ΡΠ΅ Π΄Π²Π΅ Π²ΠΈΡΡΡΠΊΠΈ (ΠΏΠΎΡΠ»Π΅Π΄Π½Π°ΡΠ° ΡΠ° Π΄Π΅Π»ΠΈ Π²ΠΈΠ»ΡΡΠΊΠ°ΡΠ° ΡΠΎ ΠΏΡΠ²Π°ΡΠ°). ΠΠΎΠ΄ΠΈΠ³Π½ΡΠ²Π°ΡΠ΅ΡΠΎ ΠΈ ΡΠΏΡΡΡΠ°ΡΠ΅ΡΠΎ Π½Π° Π²ΠΈΠ»ΡΡΠΊΠ°ΡΠ° ΡΠ΅ Π΄Π²Π΅ ΠΏΠΎΡΠ΅Π±Π½ΠΈ Π΄Π΅ΡΡΡΠ²Π°. Π‘ΠΈΡΠ΅ ΡΠΈΠ»ΠΎΠ·ΠΎΡΠΈ ΠΌΠΎΠ»ΡΠ°Ρ. ΠΠ°Π΄Π°ΡΠ°ΡΠ° Π΅ Π΄Π° ΡΠ΅ Π½Π°ΡΠ΄Π΅ ΡΠ°ΠΊΠΎΠ² Π°Π»Π³ΠΎΡΠΈΡΠ°ΠΌ ΡΡΠΎ ΡΠΈΡΠ΅ Π±ΠΈ ΡΠ°Π·ΠΌΠΈΡΠ»ΡΠ²Π°Π»Π΅ ΠΈ Π±ΠΈ Π±ΠΈΠ»Π΅ ΠΏΠΎΠ»Π½ΠΈ ΠΈ ΠΏΠΎ 54 Π³ΠΎΠ΄ΠΈΠ½ΠΈ.
ΠΡΠ²ΠΎ, Π΄Π° ΡΠ΅ ΠΎΠ±ΠΈΠ΄Π΅ΠΌΠ΅ Π΄Π° Π³ΠΎ ΡΠ΅ΡΠΈΠΌΠ΅ ΠΎΠ²ΠΎΡ ΠΏΡΠΎΠ±Π»Π΅ΠΌ ΠΏΡΠ΅ΠΊΡ ΠΊΠΎΡΠΈΡΡΠ΅ΡΠ΅ Π½Π° Π·Π°Π΅Π΄Π½ΠΈΡΠΊΠΈ ΠΏΡΠΎΡΡΠΎΡ. ΠΠΈΠ»ΡΡΠΊΠΈΡΠ΅ Π»Π΅ΠΆΠ°Ρ Π½Π° Π·Π°Π΅Π΄Π½ΠΈΡΠΊΠ°ΡΠ° ΠΌΠ°ΡΠ° ΠΈ ΡΠΈΠ»ΠΎΠ·ΠΎΡΠΈΡΠ΅ Π΅Π΄Π½ΠΎΡΡΠ°Π²Π½ΠΎ Π³ΠΈ Π·Π΅ΠΌΠ°Π°Ρ ΠΊΠΎΠ³Π° ΡΠ΅ ΠΈ Π³ΠΈ Π²ΡΠ°ΡΠ°Π°Ρ Π½Π°Π·Π°Π΄. Π’ΡΠΊΠ° ΠΈΠΌΠ° ΠΏΡΠΎΠ±Π»Π΅ΠΌΠΈ ΡΠΎ ΡΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·Π°ΡΠΈΡΠ°ΡΠ°, ΠΊΠΎΠ³Π° ΡΠΎΡΠ½ΠΎ Π΄Π° Π·Π΅ΠΌΠ°ΠΌ surebets? ΡΡΠΎ Π°ΠΊΠΎ Π½Π΅ΠΌΠ° Π²ΠΈΠ»ΡΡΠΊΠ°? ΠΠΎ, ΠΏΡΠ²ΠΎ, Π΄Π° ΠΏΠΎΡΠ½Π΅ΠΌΠ΅ ΡΠΎ ΡΠΈΠ»ΠΎΠ·ΠΎΡΠΈΡΠ΅.
ΠΠ° Π΄Π° Π·Π°ΠΏΠΎΡΠ½Π΅ΠΌΠ΅ Π½ΠΈΡΠΊΠΈ, ΠΊΠΎΡΠΈΡΡΠΈΠΌΠ΅ Π±Π°Π·Π΅Π½ ΡΠΎ Π½ΠΈΡΠΊΠΈ 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 ΡΠΎΠ·Π΄Π°Π²Π° ΠΈΠ»ΠΈ ΠΎΡΡΡΡΠ°Π½ΡΠ²Π° Π½ΠΈΡΠΊΠΈ Π²ΠΎ Π·Π°Π²ΠΈΡΠ½ΠΎΡΡ ΠΎΠ΄ Π±ΡΠΎΡΠΎΡ Π½Π° ΠΎΠ²ΠΈΠ΅ Π·Π°Π΄Π°ΡΠΈ. ΠΠ΄Π΅Π½ Π±Π°Π·Π΅Π½ Π·Π° ΡΠΈΡΠ΅ AppDomains. ΠΠ²ΠΎΡ Π±Π°Π·Π΅Π½ ΡΡΠ΅Π±Π° Π΄Π° ΡΠ΅ ΠΊΠΎΡΠΈΡΡΠΈ ΡΠ΅ΡΠΈΡΠΈ ΡΠ΅ΠΊΠΎΠ³Π°Ρ, Π±ΠΈΠ΄Π΅ΡΡΠΈ. Π½Π΅ΠΌΠ° ΠΏΠΎΡΡΠ΅Π±Π° Π΄Π° ΡΠ΅ Π·Π°ΠΌΠ°ΡΠ°ΡΠ΅ ΡΠΎ ΠΊΡΠ΅ΠΈΡΠ°ΡΠ΅, Π±ΡΠΈΡΠ΅ΡΠ΅ Π½ΠΈΡΠΊΠΈ, Π½ΠΈΠ²Π½ΠΈ ΡΠ΅Π΄ΠΈΡΠΈ ΠΈΡΠ½. ΠΠΎΠΆΠ½ΠΎ Π΅ Π±Π΅Π· Π±Π°Π·Π΅Π½, Π½ΠΎ ΠΏΠΎΡΠΎΠ° ΡΡΠ΅Π±Π° Π΄Π° Π³ΠΎ ΠΊΠΎΡΠΈΡΡΠΈΡΠ΅ Π΄ΠΈΡΠ΅ΠΊΡΠ½ΠΎ Thread
, ΠΎΠ²Π° Π΅ ΠΊΠΎΡΠΈΡΠ½ΠΎ Π·Π° ΡΠ»ΡΡΠ°ΠΈ ΠΊΠΎΠ³Π° ΡΡΠ΅Π±Π° Π΄Π° Π³ΠΎ ΡΠΌΠ΅Π½ΠΈΡΠ΅ ΠΏΡΠΈΠΎΡΠΈΡΠ΅ΡΠΎΡ Π½Π° Π½ΠΈΡΠΊΠ°ΡΠ°, ΠΊΠΎΠ³Π° ΠΈΠΌΠ°ΠΌΠ΅ Π΄ΠΎΠ»Π³Π° ΠΎΠΏΠ΅ΡΠ°ΡΠΈΡΠ°, Π·Π° Π½ΠΈΡΠΊΠ° Π²ΠΎ ΠΏΡΠ΅Π΄Π΅Π½ ΠΏΠ»Π°Π½ ΠΈΡΠ½.
Π‘ΠΎ Π΄ΡΡΠ³ΠΈ Π·Π±ΠΎΡΠΎΠ²ΠΈ, System.Threading.Tasks.Task
ΠΊΠ»Π°ΡΠ°ΡΠ° Π΅ ΠΈΡΡΠ° Thread
, Π½ΠΎ ΡΠΎ ΡΠ΅ΠΊΠ°ΠΊΠ²ΠΈ ΠΏΠΎΠ³ΠΎΠ΄Π½ΠΎΡΡΠΈ: ΡΠΏΠΎΡΠΎΠ±Π½ΠΎΡΡ Π΄Π° ΠΈΠ·Π²ΡΡΠΈΡΠ΅ Π·Π°Π΄Π°ΡΠ° ΠΏΠΎ Π±Π»ΠΎΠΊ Π΄ΡΡΠ³ΠΈ Π·Π°Π΄Π°ΡΠΈ, Π΄Π° Π³ΠΈ Π²ΡΠ°ΡΠΈΡΠ΅ ΠΎΠ΄ ΡΡΠ½ΠΊΡΠΈΠΈΡΠ΅, ΡΠ΄ΠΎΠ±Π½ΠΎ Π΄Π° Π³ΠΈ ΠΏΡΠ΅ΠΊΠΈΠ½ΡΠ²Π°ΡΠ΅ ΠΈ ΠΌΠ½ΠΎΠ³Ρ ΠΏΠΎΠ²Π΅ΡΠ΅. Π’ΠΈΠ΅ ΡΠ΅ ΠΏΠΎΡΡΠ΅Π±Π½ΠΈ Π·Π° ΠΏΠΎΠ΄Π΄ΡΡΠΊΠ° Π½Π° Π°ΡΠΈΠ½Ρ
ΡΠΎΠ½ΠΈ/ΡΠ΅ΠΊΠ°ΡΠΊΠΈ ΠΊΠΎΠ½ΡΡΡΡΠΊΡΠΈΠΈ (ΠΡΠΈΠ½Ρ
ΡΠΎΠ½Π° ΡΠ΅ΠΌΠ° Π·Π°ΡΠ½ΠΎΠ²Π°Π½Π° Π½Π° Π·Π°Π΄Π°ΡΠΈ, ΡΠΈΠ½ΡΠ°ΠΊΡΠΈΡΠΊΠΈ ΡΠ΅ΡΠ΅Ρ Π·Π° ΡΠ΅ΠΊΠ°ΡΠ΅ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ Π½Π° 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
).
ΠΠΎ, ΠΎΠ²Π° ΡΠ΅ΡΠ΅Π½ΠΈΠ΅ Π½Π΅ ΡΡΠ½ΠΊΡΠΈΠΎΠ½ΠΈΡΠ°, Π±ΠΈΠ΄Π΅ΡΡΠΈ ΡΠ΅ΠΊΠΎΠ²ΠΈΡΠ΅ Π½Π°ΡΠΊΠΎΡΠΎ (Π·Π° ΠΌΠ΅Π½Π΅ Π²ΠΎ ΡΠ΅ΠΊΡΠ½Π΄Π°) ΡΠ΅ Π±Π»ΠΎΠΊΠΈΡΠ°Π½ΠΈ: ΡΠΈΡΠ΅ ΡΠΈΠ»ΠΎΠ·ΠΎΡΠΈ ΡΠ° Π·Π΅ΠΌΠ°Π°Ρ Π»Π΅Π²Π°ΡΠ° Π²ΠΈΠ»ΡΡΠΊΠ°, Π½ΠΎ Π½Π΅ ΠΈ Π΄Π΅ΡΠ½Π°ΡΠ°. ΠΠΈΠ·Π°ΡΠ° Π²ΠΈΠ»ΡΡΠΊΠΈ ΡΠΎΠ³Π°Ρ Π³ΠΈ ΠΈΠΌΠ° Π²ΡΠ΅Π΄Π½ΠΎΡΡΠΈΡΠ΅: 1 2 3 4 5.
ΠΠ° ΡΠ»ΠΈΠΊΠ°ΡΠ°, Π±Π»ΠΎΠΊΠΈΡΠ°ΡΠ΅ Π½Π° Π½ΠΈΡΠΊΠΈ (ΡΠΎΡ-ΡΠΎΠΊΠ°ΠΊ). ΠΠ΅Π»Π΅Π½Π° - ΠΈΠ·Π²ΡΡΡΠ²Π°ΡΠ΅, ΡΡΠ²Π΅Π½Π° - ΡΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·Π°ΡΠΈΡΠ°, ΡΠΈΠ²Π° - Π½ΠΈΡΠΊΠ°ΡΠ° ΡΠΏΠΈΠ΅. Π ΠΎΠΌΠ±ΠΈΡΠ΅ Π³ΠΎ ΠΎΠ·Π½Π°ΡΡΠ²Π°Π°Ρ Π²ΡΠ΅ΠΌΠ΅ΡΠΎ Π½Π° Π·Π°ΠΏΠΎΡΠ½ΡΠ²Π°ΡΠ΅ Π½Π° Tasks.
ΠΠ»Π°Π΄ΠΎΡ ββΠ½Π° ΡΠΈΠ»ΠΎΠ·ΠΎΡΠΈΡΠ΅
ΠΠ°ΠΊΠΎ Π½Π΅ Π΅ Π½Π΅ΠΎΠΏΡ ΠΎΠ΄Π½ΠΎ Π΄Π° ΡΠ΅ ΡΠ°Π·ΠΌΠΈΡΠ»ΡΠ²Π° ΠΎΡΠΎΠ±Π΅Π½ΠΎ Π·Π° Ρ ΡΠ°Π½Π°, Π½ΠΎ Π³Π»Π°Π΄ΡΠ° Π³ΠΎ ΡΠ΅ΡΠ° ΡΠ΅ΠΊΠΎΡ Π΄Π° ΡΠ΅ ΠΎΡΠΊΠ°ΠΆΠ΅ ΠΎΠ΄ ΡΠΈΠ»ΠΎΠ·ΠΎΡΠΈΡΠ°ΡΠ°. ΠΡΠ΄Π΅ Π΄Π° ΡΠ΅ ΠΎΠ±ΠΈΠ΄Π΅ΠΌΠ΅ Π΄Π° ΡΠ° ΡΠΈΠΌΡΠ»ΠΈΡΠ°ΠΌΠ΅ ΡΠΈΡΡΠ°ΡΠΈΡΠ°ΡΠ° Π½Π° Π³Π»Π°Π΄ΡΠ²Π°ΡΠ΅ Π½Π° Π½ΠΈΡΠΊΠΈ Π²ΠΎ Π½Π°ΡΠΈΠΎΡ ΠΏΡΠΎΠ±Π»Π΅ΠΌ. ΠΠ»Π°Π΄ΡΠ²Π°ΡΠ΅ Π΅ ΠΊΠΎΠ³Π° ΡΠ΅ΡΠ΅ ΠΊΠΎΠ½Π΅Ρ, Π½ΠΎ Π±Π΅Π· Π·Π½Π°ΡΠΈΡΠ΅Π»Π½Π° ΡΠ°Π±ΠΎΡΠ°, ΡΠΎ Π΄ΡΡΠ³ΠΈ Π·Π±ΠΎΡΠΎΠ²ΠΈ, ΠΎΠ²Π° Π΅ ΠΈΡΡΠΈΠΎΡ ΡΠΎΡΡΠΎΠΊΠ°ΠΊ, ΡΠ°ΠΌΠΎ ΡΡΠΎ ΡΠ΅Π³Π° ΠΊΠΎΠ½Π΅ΡΠΎΡ Π½Π΅ ΡΠΏΠΈΠ΅, ΡΡΠΊΡ Π°ΠΊΡΠΈΠ²Π½ΠΎ Π±Π°ΡΠ° Π½Π΅ΡΡΠΎ Π΄Π° ΡΠ°Π΄Π΅, Π½ΠΎ Π½Π΅ΠΌΠ° Ρ ΡΠ°Π½Π°. ΠΠ° Π΄Π° ΠΈΠ·Π±Π΅Π³Π½Π΅ΠΌΠ΅ ΡΠ΅ΡΡΠΎ Π±Π»ΠΎΠΊΠΈΡΠ°ΡΠ΅, ΡΠ΅ ΡΠ° Π²ΡΠ°ΡΠΈΠΌΠ΅ Π²ΠΈΠ»ΡΡΠΊΠ°ΡΠ° Π°ΠΊΠΎ Π½Π΅ ΠΌΠΎΠΆΠ΅ΠΌΠ΅ Π΄Π° Π·Π΅ΠΌΠ΅ΠΌΠ΅ Π΄ΡΡΠ³Π°.
// Π’ΠΎ ΠΆΠ΅ ΡΡΠΎ ΠΈ Π² RunDeadlock, Π½ΠΎ ΡΠ΅ΠΏΠ΅ΡΡ ΠΊΠ»Π°Π΄Π΅ΠΌ Π²ΠΈΠ»ΠΊΡ Π½Π°Π·Π°Π΄ ΠΈ Π΄ΠΎΠ±Π°Π²Π»ΡΠ΅ΠΌ ΠΏΠ»ΠΎΡ
ΠΈΡ
ΡΠΈΠ»ΠΎΡΠΎΡΠΎΠ².
private void RunStarvation(int i, CancellationToken token)
{
while (true)
{
bool hasTwoForks = false;
var waitTime = TimeSpan.FromMilliseconds(50);
// ΠΠ»ΠΎΡ
ΠΎΠΉ ΡΠΈΠ»ΠΎΡΠΎΡΠΎΠ² ΠΌΠΎΠΆΠ΅Ρ ΡΠΆΠ΅ ΠΈΠΌΠ΅ΡΡ Π²ΠΈΠ»ΠΊΡ:
bool hasLeft = forks[Left(i)] == i + 1;
if (hasLeft || TakeFork(Left(i), i + 1, waitTime))
{
if (TakeFork(Right(i), i + 1, TimeSpan.Zero))
hasTwoForks = true;
else
PutFork(Left(i)); // ΠΠ½ΠΎΠ³Π΄Π° ΠΏΠ»ΠΎΡ
ΠΎΠΉ ΡΠΈΠ»ΠΎΡΠΎΡ ΠΎΡΠ΄Π°Π΅Ρ Π²ΠΈΠ»ΠΊΡ Π½Π°Π·Π°Π΄.
}
if (!hasTwoForks)
{
if (token.IsCancellationRequested) break;
continue;
}
eatenFood[i] = (eatenFood[i] + 1) % (int.MaxValue - 1);
bool goodPhilosopher = i % 2 == 0;
// Π ΠΏΠ»ΠΎΡ
ΠΎΠΉ ΡΠΈΠ»ΠΎΡΠΎΡ Π·Π°Π±ΡΠ²Π°Π΅Ρ ΠΏΠΎΠ»ΠΎΠΆΠΈΡΡ ΡΠ²ΠΎΡ Π²ΠΈΠ»ΠΊΡ ΠΎΠ±ΡΠ°ΡΠ½ΠΎ:
if (goodPhilosopher)
PutFork(Left(i));
// Π Π΅ΡΠ»ΠΈ ΠΈ ΠΏΡΠ°Π²ΡΡ Π½Π΅ ΠΏΠΎΠ»ΠΎΠΆΠΈΡ, ΡΠΎ Ρ
ΠΎΡΠΎΡΠΈΠ΅ Π±ΡΠ΄ΡΡ Π²ΠΎΠΎΠ±ΡΠ΅ Π±Π΅Π· Π΅Π΄Ρ.
PutFork(Right(i));
Think(i);
if (token.IsCancellationRequested)
break;
}
}
// Π’Π΅ΠΏΠ΅ΡΡ ΠΌΠΎΠΆΠ½ΠΎ ΠΆΠ΄Π°ΡΡ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠ΅ Π²ΡΠ΅ΠΌΡ.
bool TakeFork(int fork, int philosopher, TimeSpan? waitTime = null)
{
return SpinWait.SpinUntil(
() => Interlocked.CompareExchange(ref forks[fork], philosopher, 0) == 0,
waitTime ?? TimeSpan.FromMilliseconds(-1)
);
}
ΠΠ°ΡΠ²Π°ΠΆΠ½Π°ΡΠ° ΡΠ°Π±ΠΎΡΠ° Π·Π° ΠΎΠ²ΠΎΡ ΠΊΠΎΠ΄ Π΅ ΡΡΠΎ Π΄Π²Π°ΡΡΠ° ΠΎΠ΄ ΡΠ΅ΡΠΈΡΠΈ ΡΠΈΠ»ΠΎΠ·ΠΎΡΠΈ Π·Π°Π±ΠΎΡΠ°Π²Π°Π°Ρ Π΄Π° ΡΠ° ΡΠΏΡΡΡΠ°Ρ Π»Π΅Π²Π°ΡΠ° Π²ΠΈΠ»ΡΡΠΊΠ°. Π ΠΈΠ·Π»Π΅Π³ΡΠ²Π° Π΄Π΅ΠΊΠ° ΡΠ°Π΄Π°Ρ ΠΏΠΎΠ²Π΅ΡΠ΅ Ρ ΡΠ°Π½Π°, Π΄ΠΎΠ΄Π΅ΠΊΠ° Π΄ΡΡΠ³ΠΈ ΠΏΠΎΡΠ½ΡΠ²Π°Π°Ρ Π΄Π° Π³Π»Π°Π΄ΡΠ²Π°Π°Ρ, ΠΈΠ°ΠΊΠΎ Π½ΠΈΡΠΊΠΈΡΠ΅ ΠΈΠΌΠ°Π°Ρ ΠΈΡΡ ΠΏΡΠΈΠΎΡΠΈΡΠ΅Ρ. ΠΠ²Π΄Π΅ Π½Π΅ Π³Π»Π°Π΄ΡΠ²Π°Π°Ρ ΡΠ΅Π»ΠΎΡΠ½ΠΎ, Π·Π°ΡΠΎΠ° ΡΡΠΎ. Π»ΠΎΡΠΈΡΠ΅ ΡΠΈΠ»ΠΎΠ·ΠΎΡΠΈ ΠΏΠΎΠ½Π΅ΠΊΠΎΠ³Π°Ρ Π³ΠΈ Π²ΡΠ°ΡΠ°Π°Ρ ΡΠ²ΠΎΠΈΡΠ΅ Π²ΠΈΠ»ΡΡΠΊΠΈ. ΠΠ·Π»Π΅Π³ΡΠ²Π° Π΄Π΅ΠΊΠ° Π΄ΠΎΠ±ΡΠΈΡΠ΅ Π»ΡΡΠ΅ ΡΠ°Π΄Π°Ρ ΠΎΠΊΠΎΠ»Ρ 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 (Π½Π΅ΡΠΎΡΠ½ΠΎ, ΡΠΎΡΠ½ΠΎ). ΠΠ΅ΡΠ·ΠΈΠ½ΠΈΠΎΡ ΠΌΠ΅ΡΠΎΠ΄ 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 (mutex), Π½ΠΎ ΡΠΎ ΠΏΠΎΠ΄Π΄ΡΡΠΊΠ° Π·Π° ΡΠ΅ΠΊΠ°ΡΠ΅ Π²ΠΎ ΡΠΈΠΊΠ»ΡΡ, ΡΠ΅ΠΊΡΡΠ·ΠΈΡΠ°, ΠΌΠΎΠ΄Π΅Π»ΠΎΡ Condition Variable (ΠΏΠΎΠ²Π΅ΡΠ΅ Π·Π° ΡΠΎΠ° ΠΏΠΎΠ΄ΠΎΠ»Ρ), ΠΈΡΠ½. ΠΡΠ΄Π΅ Π΄Π° ΠΏΠΎΠ³Π»Π΅Π΄Π½Π΅ΠΌΠ΅ ΡΠ΅ΡΠ΅Π½ΠΈΠ΅ ΡΠΎ Π½Π΅Π³ΠΎ.
// Π‘ΠΏΡΡΡΠ΅ΠΌ ΠΎΠ±ΡΠ΅ΠΊΡ Π΄Π»Ρ ΠΠΎΠ½ΠΈΡΠΎΡΠ° ΠΎΡ Π²ΡΠ΅Ρ
, ΡΡΠΎΠ±Ρ Π±Π΅Π· Π΄Π΅Π΄Π»ΠΎΠΊΠΎΠ².
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 Π²ΠΈ ΠΎΠ²ΠΎΠ·ΠΌΠΎΠΆΡΠ²Π° ΠΏΠΎΠΊΠΎΠ½ΡΠΈΠ·Π½ΠΎ Π΄Π° Π³ΠΈ ΡΠΏΡΠΎΠ²Π΅Π΄Π΅ΡΠ΅ ΠΎΡΠ΅ΠΊΡΠ²Π°ΡΠ°ΡΠ° Π·Π° Π½Π΅ΠΊΠΎΡΠ° ΡΠ»ΠΎΠΆΠ΅Π½Π° ΡΠΎΡΡΠΎΡΠ±Π°. ΠΠΎ .ΠΠΠ’ Π΅ Π½Π΅ΡΠ΅Π»ΠΎΡΠ½ΠΎ ΡΠΏΠΎΡΠ΅Π΄ ΠΌΠ΅Π½Π΅ Π·Π°ΡΠΎΠ° ΡΡΠΎ Π²ΠΎ ΡΠ΅ΠΎΡΠΈΡΠ°, ΡΡΠ΅Π±Π° Π΄Π° ΠΈΠΌΠ° Π½Π΅ΠΊΠΎΠ»ΠΊΡ ΡΠ΅Π΄ΠΈΡΠΈ Π½Π° Π½Π΅ΠΊΠΎΠ»ΠΊΡ ΠΏΡΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈ (ΠΊΠ°ΠΊΠΎ Π²ΠΎ Posix Threads), Π° Π½Π΅ Π½Π° Π΅Π΄Π΅Π½ lok. Π’ΠΎΠ³Π°Ρ ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΠ΅ Π½Π°ΠΏΡΠ°Π²Π°Ρ Π·Π° ΡΠΈΡΠ΅ ΡΠΈΠ»ΠΎΠ·ΠΎΡΠΈ. ΠΠΎ, Π΄ΡΡΠΈ ΠΈ Π²ΠΎ ΠΎΠ²Π°Π° ΡΠΎΡΠΌΠ°, ΡΠΎΠ° Π²ΠΈ ΠΎΠ²ΠΎΠ·ΠΌΠΎΠΆΡΠ²Π° Π΄Π° Π³ΠΎ Π½Π°ΠΌΠ°Π»ΠΈΡΠ΅ ΠΊΠΎΠ΄ΠΎΡ.
ΠΌΠ½ΠΎΠ³Ρ ΡΠΈΠ»ΠΎΠ·ΠΎΡΠΈ ΠΈΠ»ΠΈ 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
. ΠΡΠ΅ΠΊΡ Π½Π΅Π³ΠΎ, ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΡΠ΅ΠΊΠ°ΡΠ΅ Π΄Π° Π·Π°Π²ΡΡΠΈ ΠΌΠ΅ΡΠΎΠ΄ΠΎΡ, Π΄Π° Π³ΠΎ ΠΎΡΠΊΠ°ΠΆΠ΅ΡΠ΅ ΠΈ ΡΓ¨ Π΄ΡΡΠ³ΠΎ ΡΡΠΎ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° Π½Π°ΠΏΡΠ°Π²ΠΈΡΠ΅ ΡΠΎ Task. ΠΠ½Π°ΡΡΠ΅ Π²ΠΎ ΠΌΠ΅ΡΠΎΠ΄ΠΎΡ, Π΄ΡΠΆΠ°Π²Π½Π°ΡΠ° ΠΌΠ°ΡΠΈΠ½Π° Π³ΠΎ ΠΊΠΎΠ½ΡΡΠΎΠ»ΠΈΡΠ° ΠΈΠ·Π²ΡΡΡΠ²Π°ΡΠ΅ΡΠΎ. ΠΠΎ ΠΊΡΠ°ΡΠ½Π° Π»ΠΈΠ½ΠΈΡΠ° Π΅ Π΄Π΅ΠΊΠ° Π°ΠΊΠΎ Π½Π΅ΠΌΠ° ΠΎΠ΄Π»ΠΎΠΆΡΠ²Π°ΡΠ΅, ΡΠΎΠ³Π°Ρ ΠΈΠ·Π²ΡΡΡΠ²Π°ΡΠ΅ΡΠΎ Π΅ ΡΠΈΠ½Ρ
ΡΠΎΠ½ΠΎ, Π° Π°ΠΊΠΎ ΠΈΠΌΠ°, ΡΠΎΠ³Π°Ρ Π½ΠΈΡΠΊΠ°ΡΠ° ΡΠ΅ ΠΎΡΠ»ΠΎΠ±ΠΎΠ΄ΡΠ²Π°. ΠΠ° ΠΏΠΎΠ΄ΠΎΠ±ΡΠΎ ΡΠ°Π·Π±ΠΈΡΠ°ΡΠ΅ Π½Π° ΠΎΠ²Π°, ΠΏΠΎΠ΄ΠΎΠ±ΡΠΎ Π΅ Π΄Π° ΡΠ΅ ΠΏΠΎΠ³Π»Π΅Π΄Π½Π΅ ΠΎΠ²Π°Π° Π΄ΡΠΆΠ°Π²Π½Π° ΠΌΠ°ΡΠΈΠ½Π°. ΠΠ΄ Π½ΠΈΠ² ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΠΊΡΠ΅ΠΈΡΠ°ΡΠ΅ ΡΠΈΠ½ΡΠΈΡΠΈ async
/ await
ΠΌΠ΅ΡΠΎΠ΄ΠΈ.
ΠΡΠ΄Π΅ Π΄Π° ΡΠ΅ΡΡΠΈΡΠ°ΠΌΠ΅. Π Π°Π±ΠΎΡΠ° Π½Π° 100 ΡΠΈΠ»ΠΎΠ·ΠΎΡΠΈ Π½Π° ΠΌΠ°ΡΠΈΠ½Π° ΡΠΎ 4 Π»ΠΎΠ³ΠΈΡΠΊΠΈ ΡΠ°Π΄ΡΠ°, 8 ΡΠ΅ΠΊΡΠ½Π΄ΠΈ. ΠΡΠ΅ΡΡ ΠΎΠ΄Π½ΠΎΡΠΎ ΡΠ΅ΡΠ΅Π½ΠΈΠ΅ ΡΠΎ ΠΌΠΎΠ½ΠΈΡΠΎΡ Π³ΠΈ ΠΈΡΡΡΡΠ° ΡΠ°ΠΌΠΎ ΠΏΡΠ²ΠΈΡΠ΅ 4 Π½ΠΈΡΠΊΠΈ, Π° ΠΎΡΡΠ°Π½Π°ΡΠΈΡΠ΅ Π²ΠΎΠΎΠΏΡΡΠΎ Π½Π΅ ΡΠ°Π±ΠΎΡΠ΅Π°. Π‘Π΅ΠΊΠΎΡΠ° ΠΎΠ΄ ΠΎΠ²ΠΈΠ΅ 4 Π½ΠΈΡΠΊΠΈ Π±Π΅ΡΠ΅ Π²ΠΎ ΠΌΠΈΡΡΠ²Π°ΡΠ΅ ΠΎΠΊΠΎΠ»Ρ 2 ms. Π ΡΠ΅ΡΠ΅Π½ΠΈΠ΅ΡΠΎ Π·Π° Π°ΡΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·ΠΈΡΠ°ΡΠ΅ / ΡΠ΅ΠΊΠ°ΡΠ΅ ΡΠ°Π±ΠΎΡΠΈ Π½Π° ΡΠΈΡΠ΅ 100, ΡΠΎ ΠΏΡΠΎΡΠ΅ΡΠ½ΠΎ ΡΠ΅ΠΊΠ°ΡΠ΅ ΠΎΠ΄ 6.8 ΡΠ΅ΠΊΡΠ½Π΄ΠΈ ΡΠ΅ΠΊΠΎΠ΅. Π‘Π΅ ΡΠ°Π·Π±ΠΈΡΠ°, Π²ΠΎ ΡΠ΅Π°Π»Π½ΠΈΡΠ΅ ΡΠΈΡΡΠ΅ΠΌΠΈ, ΠΌΠΈΡΡΠ²Π°ΡΠ΅ 6 ΡΠ΅ΠΊΡΠ½Π΄ΠΈ Π΅ Π½Π΅ΠΏΡΠΈΡΠ°ΡΠ»ΠΈΠ²ΠΎ ΠΈ ΠΏΠΎΠ΄ΠΎΠ±ΡΠΎ Π΅ Π΄Π° Π½Π΅ ΡΠ΅ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠ²Π°Π°Ρ ΡΠΎΠ»ΠΊΡ ΠΌΠ½ΠΎΠ³Ρ Π±Π°ΡΠ°ΡΠ° ΠΊΠ°ΠΊΠΎ ΠΎΠ²Π°. Π Π΅ΡΠ΅Π½ΠΈΠ΅ΡΠΎ ΡΠΎ ΠΠΎΠ½ΠΈΡΠΎΡ ΡΠ΅ ΠΏΠΎΠΊΠ°ΠΆΠ° Π΄Π΅ΠΊΠ° Π²ΠΎΠΎΠΏΡΡΠΎ Π½Π΅ Π΅ ΡΠΊΠ°Π»Π°Π±ΠΈΠ»Π½ΠΎ.
ΠΠ°ΠΊΠ»ΡΡΠΎΠΊ
ΠΠ°ΠΊΠΎ ΡΡΠΎ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° Π²ΠΈΠ΄ΠΈΡΠ΅ ΠΎΠ΄ ΠΎΠ²ΠΈΠ΅ ΠΌΠ°Π»ΠΈ ΠΏΡΠΈΠΌΠ΅ΡΠΈ, .NET ΠΏΠΎΠ΄Π΄ΡΠΆΡΠ²Π° ΠΌΠ½ΠΎΠ³Ρ ΠΊΠΎΠ½ΡΡΡΡΠΊΡΠΈΠΈ Π·Π° ΡΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·Π°ΡΠΈΡΠ°. Π‘Π΅ΠΏΠ°ΠΊ, Π½Π΅ Π΅ ΡΠ΅ΠΊΠΎΠ³Π°Ρ ΠΎΡΠΈΠ³Π»Π΅Π΄Π½ΠΎ ΠΊΠ°ΠΊΠΎ Π΄Π° Π³ΠΈ ΠΊΠΎΡΠΈΡΡΠΈΡΠ΅. Π‘Π΅ Π½Π°Π΄Π΅Π²Π°ΠΌ Π΄Π΅ΠΊΠ° ΠΎΠ²ΠΎΡ Π½Π°ΠΏΠΈΡ Π±Π΅ΡΠ΅ ΠΊΠΎΡΠΈΡΠ΅Π½. ΠΠ°ΡΠ΅Π³Π°, ΠΎΠ²Π° Π΅ ΠΊΡΠ°ΡΠΎΡ, Π½ΠΎ ΠΎΡΡΠ°Π½Π°Π° ΡΡΡΠ΅ ΠΌΠ½ΠΎΠ³Ρ ΠΈΠ½ΡΠ΅ΡΠ΅ΡΠ½ΠΈ ΡΠ°Π±ΠΎΡΠΈ, Π½Π° ΠΏΡΠΈΠΌΠ΅Ρ, Π½ΠΈΡΠΊΠΈ Π·Π±ΠΈΡΠΊΠΈ, TPL Dataflow, Reactive programming, Software Transaction model ΠΈΡΠ½.
ΠΠ·Π²ΠΎΡΠΈ
- ΠΠΈΠ·ΡΠ΅Π»ΠΈΠ·Π°ΡΠΈΡΠ° Π½Π° ΠΏΡΠΎΡΠΎΠΊΠΎΡ:
ΠΠΈΠ·ΡΠ΅Π»ΠΈΠ·Π°ΡΠΎΡ Π½Π° ΠΊΠΎΠ½ΠΊΡΡΠ΅Π½ΡΠΈΡΠ° - MSDN:
ΠΠΈΡΠΊΠ° ,ΠΡΠΈΠ½Ρ ΡΠΎΠ½ΠΈ ΡΠ΅ΠΌΠΈ Π½Π° ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΈΡΠ°ΡΠ΅ ΠΈ ΠΌΠ½ΠΎΠ³Ρ Π΄ΡΡΠ³ΠΈ. Π΄-Ρ - [Π ΠΈΡ ΡΠ΅Ρ] - CLR ΠΏΡΠ΅ΠΊΡ C#, ΠΠ΅ΡΡΠΈ Π ΠΈΡ ΡΠ΅Ρ
- [ΠΡΠΈΠΊ ΠΠΈΠΏΠ΅ΡΡ] -
ΠΠ° Π±ΡΠ°Π²Π°ΡΠ° ΠΠ·Π²ΠΎΡ - Π‘Π»ΠΈΠΊΠ° - βΠ’Π°Π½Ρ ΠΌΠ΅ΡΡ ΠΌΠ΅ΡΠ΅Π²ΠΈβ, Π. Π‘Π΅ΠΌΠΈΡΠ°Π΄ΡΠΊΠΈ
ΠΠ·Π²ΠΎΡ: www.habr.com