ΠΠ°Π²Π°ΠΉΡΠ΅ ΠΏΠΎΡΠΌΠΎΡΡΠΈΠΌ ΠΊΠ°ΠΊ ΡΡΡΡΠΎΠ΅Π½ΠΎ ΠΊΠΎΠ½ΠΊΡΡΠ΅Π½ΡΠ½ΠΎΠ΅ ΠΈ ΠΏΠ°ΡΠ°Π»Π»Π΅Π»ΡΠ½ΠΎΠ΅ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ Π² .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 ΡΠΎΠ·Π΄Π°Π΅Ρ ΠΈΠ»ΠΈ ΡΠ΄Π°Π»ΡΠ΅Ρ ΠΏΠΎΡΠΎΠΊΠΈ Π² Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ ΠΎΡ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²Π° ΡΡΠΈΡ
Π·Π°Π΄Π°Ρ. ΠΠ΄ΠΈΠ½ ΠΏΡΠ» Π½Π° Π²ΡΠ΅ AppDomain’Ρ. ΠΡΠΎΡ ΠΏΡΠ» ΡΡΠΎΠΈΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΠΏΠΎΡΡΠΈ Π²ΡΠ΅Π³Π΄Π°, Ρ.ΠΊ. Π½Π΅ Π½ΡΠΆΠ½ΠΎ Π·Π°ΠΌΠΎΡΠ°ΡΠΈΠ²Π°ΡΡΡΡ Ρ ΡΠΎΠ·Π΄Π°Π½ΠΈΠ΅ΠΌ, ΡΠ΄Π°Π»Π΅Π½ΠΈΠ΅ΠΌ ΠΏΠΎΡΠΎΠΊΠΎΠ², ΠΈΡ
ΠΎΡΠ΅ΡΠ΅Π΄ΡΠΌΠΈ ΠΈ ΠΏΡ. ΠΠΎΠΆΠ½ΠΎ ΠΈ Π±Π΅Π· ΠΏΡΠ»Π°, Π½ΠΎ ΡΠΎΠ³Π΄Π° ΠΏΡΠΈΠ΄Π΅ΡΡΡ Π½Π°ΠΏΡΡΠΌΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ Thread
, ΡΡΠΎ ΡΠ΅Π»Π΅ΡΠΎΠΎΠ±ΡΠ°Π·Π½ΠΎ Π΄Π»Ρ ΡΠ»ΡΡΠ°Π΅Π², ΠΊΠΎΠ³Π΄Π° Π½ΡΠΆΠ½ΠΎ ΠΏΠΎΠΌΠ΅Π½ΡΡΡ ΠΏΡΠΈΠΎΡΠΈΡΠ΅Ρ ΠΏΠΎΡΠΎΠΊΡ, ΠΊΠΎΠ³Π΄Π° Ρ Π½Π°Ρ Π΄ΠΎΠ»Π³Π°Ρ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΡ, Π΄Π»Ρ Foreground ΠΏΠΎΡΠΎΠΊΠ° ΠΈ Π΄Ρ.
ΠΡΡΠ³ΠΈΠΌΠΈ ΡΠ»ΠΎΠ²Π°ΠΌΠΈ, System.Threading.Tasks.Task
ΠΊΠ»Π°ΡΡ β ΡΡΠΎ ΡΠΎΡ ΠΆΠ΅ Thread
, Π½ΠΎ ΡΠΎ Π²ΡΡΠΊΠΈΠΌΠΈ ΡΠ΄ΠΎΠ±ΡΡΠ²Π°ΠΌΠΈ: Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΡ Π·Π°ΠΏΡΡΠΊΠ°ΡΡ ΡΠ°ΡΠΊ ΠΏΠΎΡΠ»Π΅ Π±Π»ΠΎΠΊΠ° Π΄ΡΡΠ³ΠΈΡ
ΡΠ°ΡΠΊΠΎΠ², Π²ΠΎΠ·Π²ΡΠ°ΡΠ°ΡΡ ΠΈΡ
ΠΈΠ· ΡΡΠ½ΠΊΡΠΈΠΉ, ΡΠ΄ΠΎΠ±Π½ΠΎ ΠΈΡ
ΠΏΡΠ΅ΡΡΠ²Π°ΡΡ ΠΈ ΠΌΠ½. Π΄Ρ. ΠΠ½ΠΈ Π½ΡΠΆΠ½Ρ Π΄Π»Ρ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΊΠΈ 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
ΠΈ Π΄Ρ.). ΠΠΎΡΡΠΎΠΌΡ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΈ ΠΎΡΠΈΠ±ΠΎΠΊ Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌΡ Π² ΡΠ°ΠΌΠΈΡ
ΠΏΠΎΡΠΎΠΊΠ°Ρ
ΠΈ Ρ ΠΊΠΎΡΡΠ΅ΠΊΡΠ½ΡΠΌ Π·Π°Π²Π΅ΡΡΠ΅Π½ΠΈΠ΅ΠΌ.
ΠΡΠΈΡΠΈΠ°Π½Ρ
Π₯ΠΎΡΠΎΡΠΎ, ΠΊΠ°ΠΊ Π½Π°ΠΌ ΡΠ΅ΡΠΈΡΡ ΡΡΡ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ Ρ Π²Π·Π°ΠΈΠΌΠ½ΡΠΌΠΈ Π±Π»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΠ°ΠΌΠΈ, Π³ΠΎΠ»ΠΎΠ΄Π°Π½ΠΈΠ΅ΠΌ ΠΈ ΡΠΌΠ΅ΡΡΡΠΌΠΈ? ΠΡΠ΄Π΅ΠΌ Π΄ΠΎΠΏΡΡΠΊΠ°ΡΡ ΡΠΎΠ»ΡΠΊΠΎ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΡΠΈΠ»ΠΎΡΠΎΡΠ° Π΄ΠΎ Π²ΠΈΠ»ΠΎΠΊ, Π΄ΠΎΠ±Π°Π²ΠΈΠΌ Π²Π·Π°ΠΈΠΌΠ½ΠΎΠ΅ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ (mutual exclusion) ΠΏΠΎΡΠΎΠΊΠΎΠ² Π΄Π»Ρ ΡΡΠΎΠ³ΠΎ ΠΌΠ΅ΡΡΠ°. ΠΠ°ΠΊ ΡΡΠΎ ΡΠ΄Π΅Π»Π°ΡΡ? ΠΡΠ΅Π΄ΠΏΠΎΠ»ΠΎΠΆΠΈΠΌ, ΡΡΠΎ ΡΡΠ΄ΠΎΠΌ Ρ ΡΠΈΠ»ΠΎΡΠΎΡΠ°ΠΌΠΈ ΡΡΠΎΠΈΡ ΠΎΡΠΈΡΠΈΠ°Π½Ρ, ΠΊΠΎΡΠΎΡΡΠΉ Π΄Π°Π΅Ρ ΡΠ°Π·ΡΠ΅ΡΠ΅Π½ΠΈΠ΅ ΠΊΠ°ΠΊΠΎΠΌΡ-Π½ΠΈΠ±ΡΠ΄Ρ ΠΎΠ΄Π½ΠΎΠΌΡ ΡΠΈΠ»ΠΎΡΠΎΡΡ Π²Π·ΡΡΡ Π²ΠΈΠ»ΠΊΠΈ. ΠΠ°ΠΊ Π½Π°ΠΌ ΡΠ΄Π΅Π»Π°ΡΡ ΡΡΠΎΠ³ΠΎ ΠΎΡΠΈΡΠΈΠ°Π½ΡΠ° ΠΈ ΠΊΠ°ΠΊ ΡΠΈΠ»ΠΎΡΠΎΡΡ Π±ΡΠ΄ΡΡ ΠΏΡΠΎΡΠΈΡΡ Π΅Π³ΠΎ, Π²ΠΎΠΏΡΠΎΡΡ ΠΈΠ½ΡΠ΅ΡΠ΅ΡΠ½ΡΠ΅.
ΠΡΠΎΡΡΠ΅ΠΉΡΠΈΠΉ ΡΠΏΠΎΡΠΎΠ± β ΡΡΠΎ ΠΊΠΎΠ³Π΄Π° ΡΠΈΠ»ΠΎΡΠΎΡΡ Π±ΡΠ΄ΡΡ ΠΏΡΠΎΡΡΠΎ ΠΏΠΎΡΡΠΎΡΠ½Π½ΠΎ ΠΏΡΠΎΡΠΈΡΡ ΠΎΡΠΈΡΠΈΠ°Π½ΡΠ° Π΄Π°ΡΡ Π΄ΠΎΡΡΡΠΏ ΠΊ Π²ΠΈΠ»ΠΊΠ°ΠΌ. Π’.Π΅. ΡΠ΅ΠΏΠ΅ΡΡ ΡΠΈΠ»ΠΎΡΠΎΡΡ Π±ΡΠ΄ΡΡ Π½Π΅ ΠΆΠ΄Π°ΡΡ Π²ΠΈΠ»ΠΊΡ ΡΡΠ΄ΠΎΠΌ, Π° ΠΆΠ΄Π°ΡΡ ΠΈΠ»ΠΈ ΠΏΡΠΎΡΠΈΡΡ ΠΎΡΠΈΡΠΈΠ°Π½ΡΠ°. Π‘Π½Π°ΡΠ°Π»Π° ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌ Π΄Π»Ρ ΡΡΠΎΠ³ΠΎ ΡΠΎΠ»ΡΠΊΠΎ User Space, Π² Π½Π΅ΠΌ ΠΌΡ Π½Π΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌ ΠΏΡΠ΅ΡΡΠ²Π°Π½ΠΈΡ Π΄Π»Ρ Π²ΡΠ·ΠΎΠ²Π° ΠΊΠ°ΠΊΠΈΡ -Π½ΠΈΠ±ΡΠ΄Ρ ΠΏΡΠΎΡΠ΅Π΄ΡΡ ΠΈΠ· ΡΠ΄ΡΠ° (ΠΎ Π½ΠΈΡ Π½ΠΈΠΆΠ΅).
Π Π΅ΡΠ΅Π½ΠΈΡ Π² ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ²Π΅ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ
ΠΠ΄Π΅ΡΡ Π±ΡΠ΄Π΅ΠΌ Π΄Π΅Π»Π°ΡΡ ΡΠΎΠΆΠ΅, ΡΡΠΎ ΡΠ°Π½ΡΡΠ΅ Π΄Π΅Π»Π°Π»ΠΈ Ρ ΠΎΠ΄Π½ΠΎΠΉ Π²ΠΈΠ»ΠΊΠΎΠΉ ΠΈ Π΄Π²ΡΠΌΡ ΡΠΈΠ»ΠΎΡΠΎΡΠ°ΠΌΠΈ, Π±ΡΠ΄Π΅ΠΌ ΠΊΡΡΡΠΈΡΡΡΡ Π² ΡΠΈΠΊΠ»Π΅ ΠΈ ΠΆΠ΄Π°ΡΡ. ΠΠΎ ΡΠ΅ΠΏΠ΅ΡΡ ΡΡΠΎ Π±ΡΠ΄ΡΡ Π²ΡΠ΅ ΡΠΈΠ»ΠΎΡΠΎΡΡ ΠΈ ΠΊΠ°ΠΊ Π±Ρ ΡΠΎΠ»ΡΠΊΠΎ ΠΎΠ΄Π½Π° Π²ΠΈΠ»ΠΊΠ°, Ρ.Π΅. ΠΌΠΎΠΆΠ½ΠΎ ΡΠΊΠ°Π·Π°ΡΡ Π±ΡΠ΄Π΅Ρ Π΅ΡΡΡ ΡΠΎΠ»ΡΠΊΠΎ ΡΠΎΡ ΡΠΈΠ»ΠΎΡΠΎΡ, ΠΊΠΎΡΠΎΡΡΠΉ Π²Π·ΡΠ» ΡΡΡ «Π·ΠΎΠ»ΠΎΡΡΡ Π²ΠΈΠ»ΠΊΡ» Ρ ΠΎΡΠΈΡΠΈΠ°Π½ΡΠ°. ΠΠ»Ρ ΡΡΠΎΠ³ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌ SpinLock.
private static SpinLock spinLock = new SpinLock(); // ΠΠ°Ρ "ΠΎΡΠΈΡΠΈΠ°Π½Ρ"
private void RunSpinLock(int i, CancellationToken token)
{
while (true)
{
// ΠΠ·Π°ΠΈΠΌΠ½Π°Ρ Π±Π»ΠΎΠΊΠΈΡΠΎΠ²ΠΊΠ° ΡΠ΅ΡΠ΅Π· busy waiting. ΠΡΠ·ΡΠ²Π°Π΅ΠΌ Π΄ΠΎ try, ΡΡΠΎΠ±Ρ
// Π²ΡΠ±ΡΠ°ΡΠΈΡΡ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ Π² ΡΠ»ΡΡΠ°Π΅ ΠΎΡΠΈΠ±ΠΊΠΈ Π² ΡΠ°ΠΌΠΎΠΌ SpinLock.
bool hasLock = false;
spinLock.Enter(ref hasLock);
try
{
// ΠΠ΄Π΅ΡΡ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ ΡΠΎΠ»ΡΠΊΠΎ ΠΎΠ΄ΠΈΠ½ ΠΏΠΎΡΠΎΠΊ (mutual exclusion).
forks[Left(i)] = i + 1; // ΠΠ΅ΡΠ΅ΠΌ Π²ΠΈΠ»ΠΊΡ ΡΡΠ°Π·Ρ, Π±Π΅Π· ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΡ.
forks[Right(i)] = i + 1;
eatenFood[i] = (eatenFood[i] + 1) % (int.MaxValue - 1);
forks[Left(i)] = 0;
forks[Right(i)] = 0;
}
finally
{
if(hasLock) spinLock.Exit(); // ΠΠ·Π±Π΅Π³Π°Π΅ΠΌ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ ΡΠΎ ΡΠΌΠ΅ΡΡΡΡ ΡΠΈΠ»ΠΎΡΠΎΡΠ°.
}
Think(i);
if (token.IsCancellationRequested)
break;
}
}
SpinLock
ΡΡΠΎ Π±Π»ΠΎΠΊΠΈΡΠΎΠ²ΡΠΈΠΊ, Ρ, Π³ΡΡΠ±ΠΎ Π³ΠΎΠ²ΠΎΡΡ, ΡΠ΅ΠΌ ΠΆΠ΅ while(true) { if (!lock) break; }
, Π½ΠΎ Ρ Π΅ΡΠ΅ Π±ΠΎΠ»ΡΡΠ΅ΠΉ «ΠΌΠ°Π³ΠΈΠ΅ΠΉ», ΡΠ΅ΠΌ Π² SpinWait
(ΠΊΠΎΡΠΎΡΡΠΉ ΡΠ°ΠΌ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ). Π’Π΅ΠΏΠ΅ΡΡ ΠΎΠ½ ΡΠΌΠ΅Π΅Ρ ΡΡΠΈΡΠ°ΡΡ ΠΎΠΆΠΈΠ΄Π°ΡΡΠΈΡ
, Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ ΡΡΡΠΏΠ»ΡΡΡ ΠΈΡ
ΠΈ ΠΌΠ½. Π΄Ρ. Π ΠΎΠ±ΡΠ΅ΠΌ, Π΄Π΅Π»Π°Π΅Ρ Π²ΡΡ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΠ΅ Π΄Π»Ρ ΠΎΠΏΡΠΈΠΌΠΈΠ·Π°ΡΠΈΠΈ. ΠΠΎ Π½Π°Π΄ΠΎ ΠΏΠΎΠΌΠ½ΠΈΡΡ, ΡΡΠΎ ΡΡΠΎ Π²ΡΡ ΡΠΎΡ ΠΆΠ΅ Π°ΠΊΡΠΈΠ²Π½ΡΠΉ ΡΠΈΠΊΠ», ΠΊΠΎΡΠΎΡΡΠΉ Π΅ΡΡ ΡΠ΅ΡΡΡΡΡ ΠΏΡΠΎΡΠ΅ΡΡΠΎΡΠ° ΠΈ Π΄Π΅ΡΠΆΠΈΡ ΠΏΠΎΡΠΎΠΊ, ΠΊΠΎΡΠΎΡΡΠΉ ΠΌΠΎΠΆΠ΅Ρ ΠΏΡΠΈΠ²Π΅ΡΡΠΈ ΠΊ Π³ΠΎΠ»ΠΎΠ΄Π°Π½ΠΈΡ, Π΅ΡΠ»ΠΈ ΠΎΠ΄ΠΈΠ½ ΠΈΠ· ΡΠΈΠ»ΠΎΡΠΎΡΠΎΠ² ΡΡΠ°Π½ΠΎΠ²ΠΈΡΡΡΡ ΠΏΡΠΈΠΎΡΠΈΡΠ΅ΡΠ½Π΅Π΅ Π΄ΡΡΠ³ΠΈΡ
, Π½ΠΎ Π½Π΅ ΠΈΠΌΠ΅Π΅Ρ Π·ΠΎΠ»ΠΎΡΠΎΠΉ Π²ΠΈΠ»ΠΊΠΈ (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
ΠΈ Π΄Ρ. Π‘Π°ΠΌΠ°Ρ ΠΏΠΎΠΏΡΠ»ΡΡΠ½Π°Ρ ΠΊΠΎΠ½ΡΡΡΡΠΊΡΠΈΡ Π·Π΄Π΅ΡΡ ΡΡΠΎ Monitor
, Ρ.ΠΊ. Π² C# Π΅ΡΡΡ ΠΈΠ·Π²Π΅ΡΡΠ½ΡΠΉ Π²ΡΠ΅ΠΌ lock
ΡΠΈΠ½ΡΠ°ΠΊΡΠΈΡ. Monitor
ΡΡΠΎ ΡΠΎΡ ΠΆΠ΅ ΡΠ΅ΠΌΠ°ΡΠΎΡ Ρ ΠΌΠ°ΠΊΡΠΈΠΌΠ°Π»ΡΠ½ΡΠΌ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ΠΌ 1 (ΠΌΡΡΠ΅ΠΊΡ), Π½ΠΎ Ρ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΊΠΎΠΉ ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΡ Π² ΡΠΈΠΊΠ»Π΅, ΡΠ΅ΠΊΡΡΡΠΈΠΈ, 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
, Π΄Π°ΠΆΠ΅ Π΅ΡΠ»ΠΈ Π±ΡΠ»ΠΎ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅, ΠΈ ΡΠΎΠ³Π΄Π° Π΄ΡΡΠ³ΠΎΠΉ ΠΏΠΎΡΠΎΠΊ ΠΌΠΎΠΆΠ΅Ρ ΠΈΠ·ΠΌΠ΅Π½ΠΈΡΡ ΡΠΎΡΡΠΎΡΠ½ΠΈΠ΅ ΠΎΠ±ΡΠ΅ΠΉ ΠΏΠ°ΠΌΡΡΠΈ. Π ΡΠ°ΠΊΠΈΡ
ΡΠ»ΡΡΠ°ΡΡ
ΡΠ°ΡΠ΅ Π»ΡΡΡΠ΅ ΡΡ
ΠΎΠ΄ΠΈΡΡ Π² Π΄Π΅Π΄Π»ΠΎΠΊ ΠΈΠ»ΠΈ ΠΊΠ°ΠΊ-ΡΠΎ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎ Π·Π°Π²Π΅ΡΡΠ°ΡΡ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ. ΠΡΡΠ³ΠΎΠΉ ΡΡΡΠΏΡΠΈΠ· Π² ΡΠΎΠΌ, ΡΡΠΎ Monitor ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅Ρ Π±Π»ΠΎΠΊΠΈ ΡΠΈΠ½Ρ
ΡΠΎΠ½ΠΈΠ·Π°ΡΠΈΠΈ (SyncBlock
), ΠΊΠΎΡΠΎΡΡΠ΅ Π΅ΡΡΡ Π²ΠΎ Π²ΡΠ΅Ρ
ΠΎΠ±ΡΠ΅ΠΊΡΠ°Ρ
. ΠΠΎΡΡΠΎΠΌΡ, Π΅ΡΠ»ΠΈ Π²ΡΠ±ΡΠ°Π½ Π½Π΅ΠΏΠΎΠ΄Ρ
ΠΎΠ΄ΡΡΠΈΠΉ ΠΎΠ±ΡΠ΅ΠΊΡ, ΠΌΠΎΠΆΠ½ΠΎ Π»Π΅Π³ΠΊΠΎ ΠΏΠΎΠ»ΡΡΠΈΡΡ Π΄Π΅Π΄Π»ΠΎΠΊ (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, Π΅ΡΠ»ΠΈ ΡΠ΄Π΅Π»Π°ΡΡ Π»ΠΎΠΊ Π½Π° ΠΈΠ½ΡΠ΅ΡΠ½ΠΈΡΠΎΠ²Π°Π½Π½ΡΡ ΡΡΡΠΎΠΊΡ). ΠΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌ Π²ΡΠ΅Π³Π΄Π° ΡΠΊΡΡΡΡΠΉ ΠΎΠ±ΡΠ΅ΠΊΡ Π΄Π»Ρ ΡΡΠΎΠ³ΠΎ.
Condition Variable ΠΏΠ°ΡΡΠ΅ΡΠ½ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ Π±ΠΎΠ»Π΅Π΅ ΠΊΡΠ°ΡΠΊΠΎ ΡΠ΅Π°Π»ΠΈΠ·ΠΎΠ²Π°ΡΡ ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΠ΅ ΠΊΠ°ΠΊΠΎΠ³ΠΎ-Π½ΠΈΠ±ΡΠ΄Ρ ΡΠ»ΠΎΠΆΠ½ΠΎΠ³ΠΎ ΡΡΠ»ΠΎΠ²ΠΈΡ. Π .NET ΠΎΠ½ Π½Π΅ΠΏΠΎΠ»Π½ΡΠΉ, Π½Π° ΠΌΠΎΠΉ Π²Π·Π³Π»ΡΠ΄, Ρ.ΠΊ. ΠΏΠΎ ΠΈΠ΄Π΅Π΅ ΡΠ°ΠΌ Π΄ΠΎΠ»ΠΆΠ½Ρ Π±ΡΡΡ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΠΎΡΠ΅ΡΠ΅Π΄Π΅ΠΉ Π½Π° Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΈΡ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ (ΠΊΠ°ΠΊ Π² Posix Threads), Π° Π½Π΅ Π½Π° ΠΎΠ΄Π½ΠΎΠΌ Π»ΠΎΠΊΠ΅. Π’ΠΎΠ³Π΄Π° ΠΌΠΎΠΆΠ½ΠΎ Π±ΡΠ»ΠΎ Π±Ρ ΡΠ΄Π΅Π»Π°ΡΡ ΠΈΡ Π΄Π»Ρ Π²ΡΠ΅Ρ ΡΠΈΠ»ΠΎΡΠΎΡΠΎΠ². ΠΠΎ ΠΈ Π² ΡΠ°ΠΊΠΎΠΌ Π²ΠΈΠ΄Π΅ ΠΎΠ½ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ ΡΠΎΠΊΡΠ°ΡΠΈΡΡ ΠΊΠΎΠ΄.
ΠΠ½ΠΎΠ³ΠΎ ΡΠΈΠ»ΠΎΡΠΎΡΠΎΠ² ΠΈΠ»ΠΈ async
/ 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();
}
ΠΠ΅ΡΠΎΠ΄ Ρ async
/ await
ΡΡΠ°Π½ΡΠ»ΠΈΡΡΠ΅ΡΡΡ Π² Ρ
ΠΈΡΡΡΠΉ ΠΊΠΎΠ½Π΅ΡΠ½ΡΠΉ Π°Π²ΡΠΎΠΌΠ°Ρ, ΠΊΠΎΡΠΎΡΡΠΉ ΡΡΠ°Π·Ρ Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅Ρ ΡΠ²ΠΎΠΉ Π²Π½ΡΡΡΠ΅Π½Π½ΠΈΠΉ Task
. Π§Π΅ΡΠ΅Π· Π½Π΅Π³ΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΠΆΠ΄Π°ΡΡ Π·Π°Π²Π΅ΡΡΠ΅Π½ΠΈΡ ΠΌΠ΅ΡΠΎΠ΄Π°, ΠΎΡΠΌΠ΅Π½ΡΡΡ Π΅Π³ΠΎ ΠΈ Π²ΡΡ ΠΏΡΠΎΡΠ΅Π΅, ΡΡΠΎ ΠΌΠΎΠΆΠ½ΠΎ Π΄Π΅Π»Π°ΡΡ Ρ Task. ΠΠ½ΡΡΡΠΈ ΠΌΠ΅ΡΠΎΠ΄Π°, ΠΊΠΎΠ½Π΅ΡΠ½ΡΠΉ Π°Π²ΡΠΎΠΌΠ°Ρ, ΠΊΠΎΠ½ΡΡΠΎΠ»ΠΈΡΡΠ΅Ρ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅. Π‘ΡΡΡ Π² ΡΠΎΠΌ, ΡΡΠΎ Π΅ΡΠ»ΠΈ Π½Π΅Ρ Π·Π°Π΄Π΅ΡΠΆΠΊΠΈ, ΡΠΎ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΡΠΈΠ½Ρ
ΡΠΎΠ½Π½ΠΎΠ΅, Π° Π΅ΡΠ»ΠΈ Π΅ΡΡΡ, ΡΠΎ ΠΏΠΎΡΠΎΠΊ ΠΎΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π°Π΅ΡΡΡ. ΠΠ»Ρ Π»ΡΡΡΠ΅Π³ΠΎ ΠΏΠΎΠ½ΠΈΠΌΠ°Π½ΠΈΡ ΡΡΠΎΠ³ΠΎ Π»ΡΡΡΠ΅ ΠΏΠΎΡΠΌΠΎΡΡΠ΅ΡΡ ΡΡΠΎΡ ΠΊΠΎΠ½Π΅ΡΠ½ΡΠΉ Π°Π²ΡΠΎΠΌΠ°Ρ. ΠΠΎΠΆΠ½ΠΎ ΡΠΎΠ·Π΄Π°Π²Π°ΡΡ ΡΠ΅ΠΏΠΎΡΠΊΠΈ ΠΈΠ· ΡΡΠΈΡ
async
/ await
ΠΌΠ΅ΡΠΎΠ΄ΠΎΠ².
ΠΠΎΡΠ΅ΡΡΠΈΡΡΠ΅ΠΌ. Π Π°Π±ΠΎΡΠ° 100 ΡΠΈΠ»ΠΎΡΠΎΡΠΎΠ² Π½Π° ΠΌΠ°ΡΠΈΠ½Π΅ Ρ 4 Π»ΠΎΠ³ΠΈΡΠ΅ΡΠΊΠΈΠΌΠΈ ΡΠ΄ΡΠ°ΠΌΠΈ, 8 ΡΠ΅ΠΊΡΠ½Π΄. ΠΡΠ΅Π΄ΡΠ΄ΡΡΠ΅Π΅ ΡΠ΅ΡΠ΅Π½ΠΈΠ΅ Ρ Monitor Π²ΡΠΏΠΎΠ»Π½ΡΠ»ΠΎ ΡΠΎΠ»ΡΠΊΠΎ 4 ΠΏΠ΅ΡΠ²ΡΡ ΠΏΠΎΡΠΎΠΊΠ°, Π° ΠΎΡΡΠ°Π»ΡΠ½ΡΠ΅ Π²ΠΎΠΎΠ±ΡΠ΅ Π½Π΅ Π²ΡΠΏΠΎΠ»Π½ΡΠ»ΠΈΡΡ. ΠΠ°ΠΆΠ΄ΡΠΉ ΠΈΠ· ΡΡΠΈΡ 4 ΠΏΠΎΡΠΎΠΊΠΎΠ² ΠΏΡΠΎΡΡΠ°ΠΈΠ²Π°Π» ΠΎΠΊΠΎΠ»ΠΎ 2ΠΌΡ. Π ΡΠ΅ΡΠ΅Π½ΠΈΠ΅ Ρ async / await Π²ΡΠΏΠΎΠ»Π½ΡΠ»ΠΎ Π²ΡΠ΅ 100, ΠΏΡΠΈ ΡΡΠΎΠΌ Π² ΡΡΠ΅Π΄Π½Π΅ΠΌ ΠΊΠ°ΠΆΠ΄ΡΠΉ ΠΆΠ΄Π°Π» 6.8 ΡΠ΅ΠΊΡΠ½Π΄. ΠΠΎΠ½Π΅ΡΠ½ΠΎ, Π² ΡΠ΅Π°Π»ΡΠ½ΡΡ ΡΠΈΡΡΠ΅ΠΌΠ°Ρ ΠΏΡΠΎΡΡΠ°ΠΈΠ²Π°Π½ΠΈΠ΅ ΠΏΠΎ 6 ΡΠ΅ΠΊΡΠ½Π΄ Π½Π΅ΠΏΡΠΈΠ΅ΠΌΠ»Π΅ΠΌΠΎ ΠΈ Π»ΡΡΡΠ΅ Π½Π΅ ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°ΡΡ ΡΡΠΎΠ»ΡΠΊΠΎ Π·Π°ΠΏΡΠΎΡΠΎΠ² ΡΠ°ΠΊ. Π Π΅ΡΠ΅Π½ΠΈΠ΅ ΠΆΠ΅ Ρ Monitor ΠΎΠΊΠ°Π·Π°Π»ΠΎΡΡ Π½Π΅ ΠΌΠ°ΡΡΡΠ°Π±ΠΈΡΡΠ΅ΠΌΡΠΌ Π²ΠΎΠΎΠ±ΡΠ΅.
ΠΠ°ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅
ΠΠ°ΠΊ Π²ΠΈΠ΄Π½ΠΎ ΠΈΠ· ΡΡΠΈΡ Π½Π΅Π±ΠΎΠ»ΡΡΠΈΡ ΠΏΡΠΈΠΌΠ΅ΡΠΎΠ², .NET ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°Π΅Ρ ΠΌΠ½ΠΎΠ³ΠΎ ΠΊΠΎΠ½ΡΡΡΡΠΊΡΠΈΠΉ ΡΠΈΠ½Ρ ΡΠΎΠ½ΠΈΠ·Π°ΡΠΈΠΈ. ΠΠ΅ Π²ΡΠ΅Π³Π΄Π°, Π²ΠΏΡΠΎΡΠ΅ΠΌ, ΠΎΡΠ΅Π²ΠΈΠ΄Π½ΠΎ, ΠΊΠ°ΠΊ ΠΈΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ. ΠΠ°Π΄Π΅ΡΡΡ ΡΡΠ° ΡΡΠ°ΡΡΡ ΠΎΠΊΠ°Π·Π°Π»Π°ΡΡ ΠΏΠΎΠ»Π΅Π·Π½ΠΎΠΉ. ΠΠΎΠΊΠ° Π½Π° ΡΡΠΎΠΌ Π·Π°Π²Π΅ΡΡΠ°Π΅ΠΌ, Π½ΠΎ ΠΎΡΡΠ°Π»ΠΎΡΡ Π΅ΡΠ΅ ΠΌΠ½ΠΎΠ³ΠΎ ΠΈΠ½ΡΠ΅ΡΠ΅ΡΠ½ΠΎΠ³ΠΎ, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ ΠΏΠΎΡΠΎΠΊΠΎΠ±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΡΠ΅ ΠΊΠΎΠ»Π»Π΅ΠΊΡΠΈΠΈ, TPL Dataflow, Reactive ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅, Software Transaction ΠΌΠΎΠ΄Π΅Π»Ρ ΠΈ Π΄Ρ.
ΠΡΡΠΎΡΠ½ΠΈΠΊΠΈ
- ΠΠΈΠ·ΡΠ°Π»ΠΈΠ·Π°ΡΠΈΡ ΠΏΠΎΡΠΎΠΊΠΎΠ²:
Concurrency Visualizer - MSDN:
Threading ,Asynchronous programming patterns ΠΈ ΠΌΠ½. Π΄Ρ. - [Π ΠΈΡ ΡΠ΅Ρ] β CLR via C#, Jeffrey Richter
- [ΠΡΠΈΠΊ ΠΠΈΠΏΠΏΠ΅ΡΡ] β
Π lock ΠΡΡ ΠΎΠ΄Π½ΡΠΉ ΠΊΠΎΠ΄ - ΠΠ°ΡΡΠΈΠ½ΠΊΠ° β «Π’Π°Π½Π΅Ρ ΡΡΠ΅Π΄ΠΈ ΠΌΠ΅ΡΠ΅ΠΉ», Π. Π‘Π΅ΠΌΠΈΡΠ°Π΄ΡΠΊΠΈΠΉ
ΠΡΡΠΎΡΠ½ΠΈΠΊ: habr.com