рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдЦрд┐рд▓рд╛рдП рдЧрдП рджрд╛рд░реНрд╢рдирд┐рдХ рдпрд╛ рдкреНрд░рддрд┐рд╕реНрдкрд░реНрдзреА .NET рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ

рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдЦрд┐рд▓рд╛рдП рдЧрдП рджрд╛рд░реНрд╢рдирд┐рдХ рдпрд╛ рдкреНрд░рддрд┐рд╕реНрдкрд░реНрдзреА .NET рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ

рдЙрджрд╛рд╣рд░рдг рдХреЗ рддреМрд░ рдкрд░ рдлрд┐рд▓реЙрд╕реЙрдлрд░реНрд╕ рдбрд╛рдЗрдирд┐рдВрдЧ рдкреНрд░реЙрдмреНрд▓рдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рдЖрдЗрдП рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рд╕рдорд╡рд░реНрддреА рдФрд░ рд╕рдорд╛рдирд╛рдВрддрд░ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ .Net рдореЗрдВ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддреА рд╣реИред рдпреЛрдЬрдирд╛ рдпрд╣ рд╣реИ, рдзрд╛рдЧреЗ/рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЗ рд╕рд┐рдВрдХреНрд░рдирд╛рдЗрдЬрд╝реЗрд╢рди рд╕реЗ, рдЕрднрд┐рдиреЗрддрд╛ рдореЙрдбрд▓ (рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рднрд╛рдЧреЛрдВ рдореЗрдВ)ред рд▓реЗрдЦ рдкрд╣рд▓реЗ рдкрд░рд┐рдЪрд┐рдд рдХреЗ рд▓рд┐рдП рдпрд╛ рдЖрдкрдХреЗ рдЬреНрдЮрд╛рди рдХреЛ рддрд╛рдЬрд╝рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛ рд╕рдХрддрд╛ рд╣реИред

рдРрд╕рд╛ рдмрд┐рд▓реНрдХреБрд▓ рдХреНрдпреЛрдВ рдХрд░реЗрдВ? рдЯреНрд░рд╛рдВрдЬрд┐рд╕реНрдЯрд░ рдЕрдкрдиреЗ рдиреНрдпреВрдирддрдо рдЖрдХрд╛рд░ рддрдХ рдкрд╣реБрдБрдЪ рдЬрд╛рддреЗ рд╣реИрдВ, рдореВрд░ рдХрд╛ рдирд┐рдпрдо рдкреНрд░рдХрд╛рд╢ рдХреА рдЧрддрд┐ рдХреА рд╕реАрдорд╛ рдкрд░ рдЯрд┐рдХрд╛ рд╣реЛрддрд╛ рд╣реИ рдФрд░ рдЗрд╕рд▓рд┐рдП рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рд╡реГрджреНрдзрд┐ рджреЗрдЦреА рдЬрд╛рддреА рд╣реИ, рдЕрдзрд┐рдХ рдЯреНрд░рд╛рдВрдЬрд┐рд╕реНрдЯрд░ рдмрдирд╛рдП рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕реА рд╕рдордп, рдбреЗрдЯрд╛ рдХреА рдорд╛рддреНрд░рд╛ рдмрдврд╝ рд░рд╣реА рд╣реИ, рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕рд┐рд╕реНрдЯрдо рд╕реЗ рддрддреНрдХрд╛рд▓ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреА рдЕрдкреЗрдХреНрд╖рд╛ рдХрд░рддреЗ рд╣реИрдВред рдРрд╕реА рд╕реНрдерд┐рддрд┐ рдореЗрдВ, "рд╕рд╛рдорд╛рдиреНрдп" рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ, рдЬрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдирд┐рд╖реНрдкрд╛рджрди рдереНрд░реЗрдб рд╣реЛрддрд╛ рд╣реИ, рдЕрдм рдкреНрд░рднрд╛рд╡реА рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред рдЖрдкрдХреЛ рдХрд┐рд╕реА рддрд░рд╣ рдПрдХ рд╕рд╛рде рдпрд╛ рд╕рдорд╡рд░реНрддреА рдирд┐рд╖реНрдкрд╛рджрди рдХреА рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрд╣ рд╕рдорд╕реНрдпрд╛ рд╡рд┐рднрд┐рдиреНрди рд╕реНрддрд░реЛрдВ рдкрд░ рдореМрдЬреВрдж рд╣реИ: рдереНрд░реЗрдбреНрд╕ рдХреЗ рд╕реНрддрд░ рдкрд░, рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЗ рд╕реНрддрд░ рдкрд░, рдиреЗрдЯрд╡рд░реНрдХ рдореЗрдВ рдорд╢реАрдиреЛрдВ рдХреЗ рд╕реНрддрд░ рдкрд░ (рд╡рд┐рддрд░рд┐рдд рд╕рд┐рд╕реНрдЯрдо)ред .NET рдХреЗ рдкрд╛рд╕ рдРрд╕реА рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рдЬрд▓реНрджреА рдФрд░ рдХреБрд╢рд▓рддрд╛ рд╕реЗ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдЪреНрдЪ-рдЧреБрдгрд╡рддреНрддрд╛, рд╕рдордп-рдкрд░реАрдХреНрд╖рдгрд┐рдд рдкреНрд░реМрджреНрдпреЛрдЧрд┐рдХрд┐рдпрд╛рдБ рд╣реИрдВред

рдХрд╛рд░реНрдп

Edsger Dijkstra рдиреЗ 1965 рдХреА рд╢реБрд░реБрдЖрдд рдореЗрдВ рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рдЕрдкрдиреЗ рдЫрд╛рддреНрд░реЛрдВ рдХреЗ рд╕рд╛рдордиреЗ рд░рдЦрд╛ред рд╕реНрдерд╛рдкрд┐рдд рд╕реВрддреНрд░ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИред рджрд╛рд░реНрд╢рдирд┐рдХреЛрдВ рдХреА рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд (рдЖрдорддреМрд░ рдкрд░ рдкрд╛рдВрдЪ) рд╕рдВрдЦреНрдпрд╛ рдФрд░ рд╕рдорд╛рди рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдХрд╛рдВрдЯреЗ рд╣реЛрддреЗ рд╣реИрдВред рд╡реЗ рдПрдХ рдЧреЛрд▓ рдореЗрдЬ рдкрд░ рдмреИрдарддреЗ рд╣реИрдВ, рдЙрдирдХреЗ рдмреАрдЪ рдХрд╛рдВрдЯреЗ рд╣реЛрддреЗ рд╣реИрдВред рджрд╛рд░реНрд╢рдирд┐рдХ рдЕрдкрдиреА рдЕрдВрддрд╣реАрди рднреЛрдЬрди рдХреА рдерд╛рд▓реА рд╕реЗ рдЦрд╛ рд╕рдХрддреЗ рд╣реИрдВ, рд╕реЛрдЪ рд╕рдХрддреЗ рд╣реИрдВ рдпрд╛ рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдПрдХ рджрд╛рд░реНрд╢рдирд┐рдХ рдХреЛ рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рджреЛ рдХрд╛рдВрдЯреЗ рд▓реЗрдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИ (рдЖрдЦрд┐рд░реА рд╡рд╛рд▓рд╛ рдкрд╣рд▓реЗ рдХреЗ рд╕рд╛рде рдХрд╛рдВрдЯрд╛ рд╕рд╛рдЭрд╛ рдХрд░рддрд╛ рд╣реИ)ред рдХрд╛рдВрдЯреЗ рдХреЛ рдЙрдард╛рдирд╛ рдФрд░ рдиреАрдЪреЗ рд░рдЦрдирд╛ рджреЛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдХреНрд░рд┐рдпрд╛рдПрдВ рд╣реИрдВред рд╕рднреА рджрд╛рд░реНрд╢рдирд┐рдХ рдореМрди рд╣реИрдВред рдХрд╛рдо рд╣реИ рдРрд╕рд╛ рдПрд▓реНрдЧреЛрд░рд┐рджреНрдо рдвреВрдВрдврд╝рдирд╛ рдХрд┐ рдпреЗ рд╕рднреА 54 рд╕рд╛рд▓ рдмрд╛рдж рднреА рд╕реЛрдЪреЗрдВрдЧреЗ рдФрд░ рднрд░реЗ рд░рд╣реЗрдВрдЧреЗред

рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЖрдЗрдП рд╕рд╛рдЭрд╛ рд╕реНрдерд╛рди рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред рдХрд╛рдВрдЯреЗ рдЖрдо тАЛтАЛрдореЗрдЬ рдкрд░ рдкрдбрд╝реЗ рд╣реЛрддреЗ рд╣реИрдВ рдФрд░ рджрд╛рд░реНрд╢рдирд┐рдХ рдЙрдиреНрд╣реЗрдВ рддрднреА рд▓реЗ рд▓реЗрддреЗ рд╣реИрдВ рдЬрдм рд╡реЗ рд╣реЛрддреЗ рд╣реИрдВ рдФрд░ рдЙрдиреНрд╣реЗрдВ рд╡рд╛рдкрд╕ рд░рдЦ рджреЗрддреЗ рд╣реИрдВред рдпрд╣рд╛рдВ рд╕рд┐рдВрдХреНрд░реЛрдирд╛рдЗрдЬрд╝реЗрд╢рди рдХреА рд╕рдорд╕реНрдпрд╛рдПрдВ рд╣реИрдВ, рдЕрдЪреВрдХ рджрд╛рдВрд╡ рдХрдм рд▓реЗрдирд╛ рд╣реИ? рдпрджрд┐ рдХрд╛рдВрдЯрд╛ рди рд╣реЛ рддреЛ рдХреНрдпрд╛ рд╣реЛрдЧрд╛? рдЖрджрд┐ред рд▓реЗрдХрд┐рди рдкрд╣рд▓реЗ, рдЖрдЗрдП рджрд╛рд░реНрд╢рдирд┐рдХреЛрдВ рд╕реЗ рд╢реБрд░реБрдЖрдд рдХрд░реЗрдВред

рдереНрд░реЗрдб рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдереНрд░реЗрдб рдкреВрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ Task.Run рддрд░реАрдХрд╛:

var cancelTokenSource = new CancellationTokenSource();
Action<int> create = (i) => RunPhilosopher(i, cancelTokenSource.Token);
for (int i = 0; i < philosophersAmount; i++) 
{
    int icopy = i;
    // ╨Я╨╛╨╝╨╡╤Б╤В╨╕╤В╤М ╨╖╨░╨┤╨░╤З╤Г ╨▓ ╨╛╤З╨╡╤А╨╡╨┤╤М ╨┐╤Г╨╗╨░ ╨┐╨╛╤В╨╛╨║╨╛╨▓. ╨Ь╨╡╤В╨╛╨┤ RunDeadlock ╨╜╨╡ ╨╖╨░╨┐╤Г╤Б╨║╨░╨╡╤В╤М╤Б╤П 
    // ╤Б╤А╨░╨╖╤Г, ╨░ ╨╢╨┤╨╡╤В ╤Б╨▓╨╛╨╡╨│╨╛ ╨┐╨╛╤В╨╛╨║╨░. ╨Р╤Б╨╕╨╜╤Е╤А╨╛╨╜╨╜╤Л╨╣ ╨╖╨░╨┐╤Г╤Б╨║.
    philosophers[i] = Task.Run(() => create(icopy), cancelTokenSource.Token);
}

рдереНрд░реЗрдб рдкреВрд▓ рдХреЛ рдереНрд░реЗрдб рдирд┐рд░реНрдорд╛рдг рдФрд░ рд╡рд┐рд▓реЛрдкрди рдХреЛ рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдЗрд╕ рдкреВрд▓ рдореЗрдВ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рдХрддрд╛рд░ рд╣реИ рдФрд░ рд╕реАрдПрд▓рдЖрд░ рдЗрди рдХрд╛рд░реНрдпреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдзрд╛рдЧреЗ рдмрдирд╛рддрд╛ рд╣реИ рдпрд╛ рд╣рдЯрд╛ рджреЗрддрд╛ рд╣реИред рд╕рднреА AppDomains рдХреЗ рд▓рд┐рдП рдПрдХ рдкреВрд▓ред рдЗрд╕ рдкреВрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рд▓рдЧрднрдЧ рд╣рдореЗрд╢рд╛ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдХреНрдпреЛрдВрдХрд┐ред рдзрд╛рдЧреЗ рдмрдирд╛рдиреЗ, рд╣рдЯрд╛рдиреЗ, рдЙрдирдХреА рдХрддрд╛рд░реЛрдВ рдЖрджрд┐ рд╕реЗ рдкрд░реЗрд╢рд╛рди рд╣реЛрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред рдкреВрд▓ рдХреЗ рдмрд┐рдирд╛ рдпрд╣ рд╕рдВрднрд╡ рд╣реИ, рд▓реЗрдХрд┐рди рдлрд┐рд░ рдЖрдкрдХреЛ рдЗрд╕реЗ рд╕реАрдзреЗ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ Thread, рдпрд╣ рдЙрди рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реИ рдЬрдм рдЖрдкрдХреЛ рдХрд┐рд╕реА рдереНрд░реЗрдб рдХреА рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рдХреЛ рдмрджрд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдЬрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рд▓рдВрдмрд╛ рдСрдкрд░реЗрд╢рди рд╣реЛрддрд╛ рд╣реИ, рдлреЛрд░рдЧреНрд░рд╛рдЙрдВрдб рдереНрд░реЗрдб рдЖрджрд┐ рдХреЗ рд▓рд┐рдПред

рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, System.Threading.Tasks.Task рд╡рд░реНрдЧ рд╕рдорд╛рди рд╣реИ Thread, рд▓реЗрдХрд┐рди рд╕рднреА рдкреНрд░рдХрд╛рд░ рдХреА рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХреЗ рд╕рд╛рде: рдЕрдиреНрдп рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдПрдХ рдмреНрд▓реЙрдХ рдХреЗ рдмрд╛рдж рдПрдХ рдХрд╛рд░реНрдп рдХреЛ рдЪрд▓рд╛рдиреЗ рдХреА рдХреНрд╖рдорддрд╛, рдЙрдиреНрд╣реЗрдВ рдХрд╛рд░реНрдпреЛрдВ рд╕реЗ рд╡рд╛рдкрд╕ рдХрд░рдирд╛, рдЖрд╕рд╛рдиреА рд╕реЗ рдЙрдиреНрд╣реЗрдВ рдмрд╛рдзрд┐рдд рдХрд░рдирд╛, рдФрд░ рдмрд╣реБрдд рдХреБрдЫред рдЖрджрд┐ред рдЙрдиреНрд╣реЗрдВ async / рдкреНрд░рддреАрдХреНрд╖рд╛ рдирд┐рд░реНрдорд╛рдг (рдХрд╛рд░реНрдп-рдЖрдзрд╛рд░рд┐рдд рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рдкреИрдЯрд░реНрди, 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), рдЬреЛ рдкрд░рдорд╛рдгреБ рдЕрдиреБрдХреНрд░рдорд┐рдХ рдкрдврд╝рдиреЗ рдФрд░ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрдореГрддрд┐ рдХрд╛ рдПрдХ рдЯреБрдХрдбрд╝рд╛ рддрд╛рд▓рд╛ рд▓рдЧрд╛ рджреЗрддрд╛ рд╣реИред рдФрд░ рд╕реНрдкрд┐рдирд╡рд╛рдЗрдЯ рдирд┐рд░реНрдорд╛рдг рдХреЗ рдмрд░рд╛рдмрд░ рд╣реИ while(true) рдХреЗрд╡рд▓ рдереЛрдбрд╝реЗ "рдЬрд╛рджреВ" рдХреЗ рд╕рд╛рде - рдзрд╛рдЧрд╛ рдкреНрд░реЛрд╕реЗрд╕рд░ рд▓реЗрддрд╛ рд╣реИ (Thread.SpinWait), рд▓реЗрдХрд┐рди рдХрднреА-рдХрднреА рдирд┐рдпрдВрддреНрд░рдг рдХреЛ рджреВрд╕рд░реЗ рдереНрд░реЗрдб рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░ рджреЗрддрд╛ рд╣реИ (Thread.Yeild) рдпрд╛ рд╕реЛ рдЬрд╛рддрд╛ рд╣реИ (Thread.Sleep).

рд▓реЗрдХрд┐рди рдпрд╣ рд╕рдорд╛рдзрд╛рди рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛, рдХреНрдпреЛрдВрдХрд┐ рдкреНрд░рд╡рд╛рд╣ рдЬрд▓реНрдж рд╣реА (рдореЗрд░реЗ рд▓рд┐рдП рдПрдХ рд╕реЗрдХрдВрдб рдХреЗ рднреАрддрд░) рдЕрд╡рд░реБрджреНрдз рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ: рд╕рднреА рджрд╛рд░реНрд╢рдирд┐рдХ рдЕрдкрдирд╛ рдмрд╛рдпрд╛рдВ рдХрд╛рдВрдЯрд╛ рд▓реЗрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╕рд╣реА рдирд╣реАрдВред рдХрд╛рдВрдЯреЗ рд╕рд░рдгреА рдореЗрдВ рддрдм рдорд╛рди рд╣реЛрддреЗ рд╣реИрдВ: 1 2 3 4 5ред

рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдЦрд┐рд▓рд╛рдП рдЧрдП рджрд╛рд░реНрд╢рдирд┐рдХ рдпрд╛ рдкреНрд░рддрд┐рд╕реНрдкрд░реНрдзреА .NET рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ

рдЪрд┐рддреНрд░ рдореЗрдВ, рдмреНрд▓реЙрдХрд┐рдВрдЧ рдереНрд░реЗрдбреНрд╕ (рдЧрддрд┐рд░реЛрдз)ред рд╣рд░рд╛ - рдирд┐рд╖реНрдкрд╛рджрди, рд▓рд╛рд▓ - рддреБрд▓реНрдпрдХрд╛рд▓рди, рдЧреНрд░реЗ - рдзрд╛рдЧрд╛ рд╕реЛ рд░рд╣рд╛ рд╣реИред рд╕рдордЪрддреБрд░реНрднреБрдЬ рдХрд╛рд░реНрдп рдХреЗ рдкреНрд░рд╛рд░рдВрдн рд╕рдордп рдХрд╛ рд╕рдВрдХреЗрдд рджреЗрддреЗ рд╣реИрдВред

рджрд╛рд░реНрд╢рдирд┐рдХреЛрдВ рдХреА рднреВрдЦ

рд╣рд╛рд▓рд╛рдВрдХрд┐ рднреЛрдЬрди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рд╕реЛрдЪрдирд╛ рдЬрд░реВрд░реА рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рднреВрдЦ рдХрд┐рд╕реА рдХреЛ рднреА рджрд░реНрд╢рди рд╕реЗ рд╡рд┐рдореБрдЦ рдХрд░ рджреЗрддреА рд╣реИред рдЖрдЗрдП рд╣рдорд╛рд░реА рд╕рдорд╕реНрдпрд╛ рдореЗрдВ рдзрд╛рдЧреЗ рдХреА рднреБрдЦрдорд░реА рдХреА рд╕реНрдерд┐рддрд┐ рдХреЛ рдЕрдиреБрдХрд░рдг рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред рднреБрдЦрдорд░реА рддрдм рд╣реЛрддреА рд╣реИ рдЬрдм рдПрдХ рдзрд╛рдЧрд╛ рдЪрд▓ рд░рд╣рд╛ рд╣реЛрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдорд╣рддреНрд╡рдкреВрд░реНрдг рдХрд╛рдо рдХреЗ рдмрд┐рдирд╛, рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, рдпрд╣ рд╡рд╣реА рдЧрддрд┐рд░реЛрдз рд╣реИ, рдХреЗрд╡рд▓ рдЕрдм рдзрд╛рдЧрд╛ рд╕реЛ рдирд╣реАрдВ рд░рд╣рд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рдХреНрд░рд┐рдп рд░реВрдк рд╕реЗ рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдвреВрдВрдв рд░рд╣рд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдХреЛрдИ рднреЛрдЬрди рдирд╣реАрдВ рд╣реИред рдмрд╛рд░-рдмрд╛рд░ рдЕрд╡рд░реБрджреНрдз рд╣реЛрдиреЗ рд╕реЗ рдмрдЪрдиреЗ рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рд╣рдо рджреВрд╕рд░рд╛ рдХрд╛рдВрдЯрд╛ рдирд╣реАрдВ рд▓реЗ рд╕рдХрддреЗ рд╣реИрдВ рддреЛ рд╣рдо рд╡рд╛рдкрд╕ рд░рдЦ рджреЗрдВрдЧреЗред

// ╨в╨╛ ╨╢╨╡ ╤З╤В╨╛ ╨╕ ╨▓ 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 рдЧреБрдирд╛ рдХрдо рдЦрд╛рддреЗ рд╣реИрдВред рддреЛ рдХреЛрдб рдореЗрдВ рдПрдХ рдЫреЛрдЯреА рд╕реА рддреНрд░реБрдЯрд┐ рдкреНрд░рджрд░реНрд╢рди рдореЗрдВ рдЧрд┐рд░рд╛рд╡рдЯ рдХреА рдУрд░ рд▓реЗ рдЬрд╛рддреА рд╣реИред рдпрд╣рд╛рдБ рдпрд╣ рднреА рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реИ рдХрд┐ рдПрдХ рджреБрд░реНрд▓рдн рд╕реНрдерд┐рддрд┐ рддрдм рд╕рдВрднрд╡ рд╣реЛрддреА рд╣реИ рдЬрдм рд╕рднреА рджрд╛рд░реНрд╢рдирд┐рдХ рдмрд╛рдпрд╛рдБ рдХрд╛рдБрдЯрд╛ рдЙрдард╛рддреЗ рд╣реИрдВ, рдХреЛрдИ рджрд╛рдпрд╛рдБ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ, рд╡реЗ рдмрд╛рдПрдБ рдбрд╛рд▓рддреЗ рд╣реИрдВ, рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рддреЗ рд╣реИрдВ, рдлрд┐рд░ рд╕реЗ рдмрд╛рдПрдБ рд▓реЗрддреЗ рд╣реИрдВ, рдЖрджрд┐ред рдпрд╣ рд╕реНрдерд┐рддрд┐ рднреА рдПрдХ рдЧрддрд┐рд░реЛрдз рдХреА рддрд░рд╣ рднреБрдЦрдорд░реА рд╣реИред рдореИрдВ рдЗрд╕реЗ рджреЛрд╣рд░рд╛рдиреЗ рдореЗрдВ рдЕрд╕рдлрд▓ рд░рд╣рд╛ред рдиреАрдЪреЗ рдПрдХ рдРрд╕реА рд╕реНрдерд┐рддрд┐ рдХреА рддрд╕реНрд╡реАрд░ рд╣реИ рдЬрд╣рд╛рдВ рджреЛ рдмреБрд░реЗ рджрд╛рд░реНрд╢рдирд┐рдХреЛрдВ рдиреЗ рджреЛрдиреЛрдВ рдХрд╛рдВрдЯреЗ рд▓реЗ рд▓рд┐рдП рд╣реИрдВ рдФрд░ рджреЛ рдЕрдЪреНрдЫреЗ рджрд╛рд░реНрд╢рдирд┐рдХ рднреВрдЦ рд╕реЗ рдорд░ рд░рд╣реЗ рд╣реИрдВред

рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдЦрд┐рд▓рд╛рдП рдЧрдП рджрд╛рд░реНрд╢рдирд┐рдХ рдпрд╛ рдкреНрд░рддрд┐рд╕реНрдкрд░реНрдзреА .NET рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ

рдпрд╣рд╛рдВ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдзрд╛рдЧреЗ рдХрднреА-рдХрднреА рдЬрд╛рдЧрддреЗ рд╣реИрдВ рдФрд░ рд╕рдВрд╕рд╛рдзрди рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВред рдЪрд╛рд░ рдореЗрдВ рд╕реЗ рджреЛ рдХреЛрд░ рдХреБрдЫ рдирд╣реАрдВ рдХрд░рддреЗ (рдКрдкрд░ рд╣рд░рд╛ рдЧреНрд░рд╛рдл)ред

рдПрдХ рджрд╛рд░реНрд╢рдирд┐рдХ рдХреА рдореГрддреНрдпреБ

рдареАрдХ рд╣реИ, рдПрдХ рдФрд░ рд╕рдорд╕реНрдпрд╛ рдЬреЛ рджрд╛рд░реНрд╢рдирд┐рдХреЛрдВ рдХреЗ рд╢рд╛рдирджрд╛рд░ рд░рд╛рддреНрд░рд┐рднреЛрдЬ рдХреЛ рдмрд╛рдзрд┐рдд рдХрд░ рд╕рдХрддреА рд╣реИ, рдЕрдЧрд░ рдЙрдирдореЗрдВ рд╕реЗ рдПрдХ рдЕрдЪрд╛рдирдХ рд╣рд╛рдереЛрдВ рдореЗрдВ рдХрд╛рдВрдЯреЗ рд▓реЗрдХрд░ рдорд░ рдЬрд╛рддрд╛ рд╣реИ (рдФрд░ рд╡реЗ рдЙрд╕реЗ рдЙрд╕реА рддрд░рд╣ рджрдлрдирд╛ рджреЗрдВрдЧреЗ)ред рдлрд┐рд░ рдкрдбрд╝реЛрд╕рд┐рдпреЛрдВ рдХреЛ рд░рд╛рдд рдХреЗ рдЦрд╛рдиреЗ рдХреЗ рдмрд┐рдирд╛ рдЫреЛрдбрд╝ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдЖрдк рд╕реНрд╡рдпрдВ рдЗрд╕ рдорд╛рдорд▓реЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЛрдб рдХреЗ рд╕рд╛рде рдЖ рд╕рдХрддреЗ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЗрд╕реЗ рдлреЗрдВрдХ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ NullReferenceException рджрд╛рд░реНрд╢рдирд┐рдХ рдХрд╛рдВрдЯреЗ рд▓реЗрдиреЗ рдХреЗ рдмрд╛рджред рдФрд░, рд╡реИрд╕реЗ, рдЕрдкрд╡рд╛рдж рдХреЛ рд╕рдВрднрд╛рд▓рд╛ рдирд╣реАрдВ рдЬрд╛рдПрдЧрд╛ рдФрд░ рдХреЙрд▓рд┐рдВрдЧ рдХреЛрдб рдЗрд╕реЗ рдкрдХрдбрд╝ рдирд╣реАрдВ рдкрд╛рдПрдЧрд╛ (рдЗрд╕рдХреЗ рд▓рд┐рдП AppDomain.CurrentDomain.UnhandledException рдФрд░ рдЖрджрд┐ред)ред рдЗрд╕рд▓рд┐рдП, рддреНрд░реБрдЯрд┐ рд╕рдВрдЪрд╛рд▓рдХреЛрдВ рдХреЛ рд╕реНрд╡рдпрдВ рдереНрд░реЗрдбреНрд╕ рдореЗрдВ рдФрд░ рд╕реБрдВрджрд░ рд╕рдорд╛рдкреНрддрд┐ рдХреЗ рд╕рд╛рде рдЖрд╡рд╢реНрдпрдХ рд╣реИрдВред

Oficiant

рдареАрдХ рд╣реИ, рд╣рдо рдЗрд╕ рдЧрддрд┐рд░реЛрдз, рднреБрдЦрдорд░реА рдФрд░ рдореМрдд рдХреА рд╕рдорд╕реНрдпрд╛ рдХреЛ рдХреИрд╕реЗ рд╕реБрд▓рдЭрд╛ рд╕рдХрддреЗ рд╣реИрдВ? рд╣рдо рдХреЗрд╡рд▓ рдПрдХ рджрд╛рд░реНрд╢рдирд┐рдХ рдХреЛ рдХрд╛рдВрдЯреЗ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдВрдЧреЗ, рдЗрд╕ рд╕реНрдерд╛рди рдХреЗ рд▓рд┐рдП рдзрд╛рдЧреЗ рдХрд╛ рдкрд╛рд░рд╕реНрдкрд░рд┐рдХ рдмрд╣рд┐рд╖реНрдХрд░рдг рдЬреЛрдбрд╝реЗрдВред рдЗрд╕реЗ рдХреИрд╕реЗ рдХрд░рдирд╛ рд╣реИ? рдорд╛рди рд▓реАрдЬрд┐рдП рдХрд┐ рдПрдХ рд╡реЗрдЯрд░ рджрд╛рд░реНрд╢рдирд┐рдХреЛрдВ рдХреЗ рдмрдЧрд▓ рдореЗрдВ рдЦрдбрд╝рд╛ рд╣реИ, рдЬреЛ рдХрд┐рд╕реА рдПрдХ рджрд╛рд░реНрд╢рдирд┐рдХ рдХреЛ рдХрд╛рдВрдЯреЗ рд▓реЗрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рд╣рдо рдЗрд╕ рд╡реЗрдЯрд░ рдХреЛ рдХреИрд╕реЗ рдмрдирд╛рдПрдВрдЧреЗ рдФрд░ рджрд╛рд░реНрд╢рдирд┐рдХ рдЙрд╕рд╕реЗ рдХреИрд╕реЗ рдкреВрдЫреЗрдВрдЧреЗ, рд╕рд╡рд╛рд▓ рджрд┐рд▓рдЪрд╕реНрдк рд╣реИрдВред

рд╕рдмрд╕реЗ рд╕рд░рд▓ рддрд░реАрдХрд╛ рд╣реИ рдЬрдм рджрд╛рд░реНрд╢рдирд┐рдХ рдмрд╕ рд╡реЗрдЯрд░ рд╕реЗ рд▓рдЧрд╛рддрд╛рд░ рдХрд╛рдВрдЯреЗ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣реЗрдВрдЧреЗред рд╡реЗред рдЕрдм рджрд╛рд░реНрд╢рдирд┐рдХ рдкрд╛рд╕ рдХреЗ рдХрд╛рдВрдЯреЗ рдХрд╛ рдЗрдВрддрдЬрд╛рд░ рдирд╣реАрдВ рдХрд░реЗрдВрдЧреЗ, рдмрд▓реНрдХрд┐ рдЗрдВрддрдЬрд╛рд░ рдХрд░реЗрдВрдЧреЗ рдпрд╛ рд╡реЗрдЯрд░ рд╕реЗ рдкреВрдЫреЗрдВрдЧреЗред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рдЗрд╕рдХреЗ рд▓рд┐рдП рдХреЗрд╡рд▓ рдпреВрдЬрд░ рд╕реНрдкреЗрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдЗрд╕рдореЗрдВ рд╣рдо рдХрд░реНрдиреЗрд▓ рд╕реЗ рдХрд┐рд╕реА рднреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрдВрдЯрд░рдкреНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ (рдЙрдирдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдиреАрдЪреЗ)ред

рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реНрдерд╛рди рдореЗрдВ рд╕рдорд╛рдзрд╛рди

рдпрд╣рд╛рдВ рд╣рдо рд╡рд╣реА рдХрд░реЗрдВрдЧреЗ рдЬреЛ рдПрдХ рдХрд╛рдВрдЯреЗ рдФрд░ рджреЛ рджрд╛рд░реНрд╢рдирд┐рдХреЛрдВ рдХреЗ рд╕рд╛рде рдХрд░рддреЗ рдереЗ, рд╣рдо рдПрдХ рдЪрдХреНрд░ рдореЗрдВ рдШреВрдореЗрдВрдЧреЗ рдФрд░ рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░реЗрдВрдЧреЗред рд▓реЗрдХрд┐рди рдЕрдм рдпрд╣ рд╕рднреА рджрд╛рд░реНрд╢рдирд┐рдХ рд╣реЛрдВрдЧреЗ рдФрд░ рдЬреИрд╕рд╛ рдХрд┐ рдпрд╣ рдерд╛, рдХреЗрд╡рд▓ рдПрдХ рдХрд╛рдВрдЯрд╛, рдпрд╛рдиреАред рдпрд╣ рдХрд╣рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рд╡реЗрдЯрд░ рд╕реЗ рдпрд╣ "рд╕реБрдирд╣рд░рд╛ рдХрд╛рдВрдЯрд╛" рд▓реЗрдиреЗ рд╡рд╛рд▓реЗ рджрд╛рд░реНрд╢рдирд┐рдХ рд╣реА рдЦрд╛рдПрдВрдЧреЗред рдЗрд╕рдХреЗ рд▓рд┐рдП рд╣рдо рд╕реНрдкрд┐рдирд▓реЙрдХ рдХрд╛ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд░рддреЗ рд╣реИрдВред

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 (рдЬреЛ рд╡рд╣рд╛рдБ рдкреНрд░рдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ)ред рдЕрдм рд╡рд╣ рдЬрд╛рдирддрд╛ рд╣реИ рдХрд┐ рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рдиреЗ рд╡рд╛рд▓реЛрдВ рдХреЛ рдХреИрд╕реЗ рдЧрд┐рдирдирд╛ рд╣реИ, рдЙрдиреНрд╣реЗрдВ рдереЛрдбрд╝рд╛ рд╕реБрд▓рд╛рдирд╛ рд╣реИ, рдФрд░ рдмрд╣реБрдд рдХреБрдЫред рдЖрджрд┐ рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рдЕрдиреБрдХреВрд▓рди рдХреЗ рд▓рд┐рдП рд╣рд░ рд╕рдВрднрд╡ рдкреНрд░рдпрд╛рд╕ рдХрд░рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рд╣рдореЗрдВ рдпрд╛рдж рд░рдЦрдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рдпрд╣ рдЕрднреА рднреА рд╡рд╣реА рд╕рдХреНрд░рд┐рдп рдЪрдХреНрд░ рд╣реИ рдЬреЛ рдкреНрд░реЛрд╕реЗрд╕рд░ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреЛ рдЦрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдкреНрд░рд╡рд╛рд╣ рдХреЛ рдмрдирд╛рдП рд░рдЦрддрд╛ рд╣реИ, рдЬреЛ рднреБрдЦрдорд░реА рдХрд╛ рдХрд╛рд░рдг рдмрди рд╕рдХрддрд╛ рд╣реИ рдпрджрд┐ рджрд╛рд░реНрд╢рдирд┐рдХреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рджреВрд╕рд░реЛрдВ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдЕрдзрд┐рдХ рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рдмрди рдЬрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕рдореЗрдВ рд╕реБрдирд╣рд░рд╛ рдХрд╛рдВрдЯрд╛ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ (рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рдЙрд▓рдЯрд╛ рд╕рдорд╕реНрдпрд╛) . рдЗрд╕рд▓рд┐рдП, рд╣рдо рдЗрд╕реЗ рдХреЗрд╡рд▓ рд╕рд╛рдЭрд╛ рд╕реНрдореГрддрд┐ рдореЗрдВ рдмрд╣реБрдд рд╣реА рдХрдо рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдмрд┐рдирд╛ рдХрд┐рд╕реА рддреГрддреАрдп-рдкрдХреНрд╖ рдХреЙрд▓, рдиреЗрд╕реНрдЯреЗрдб рд▓реЙрдХ рдФрд░ рдЕрдиреНрдп рдЖрд╢реНрдЪрд░реНрдп рдХреЗред

рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдЦрд┐рд▓рд╛рдП рдЧрдП рджрд╛рд░реНрд╢рдирд┐рдХ рдпрд╛ рдкреНрд░рддрд┐рд╕реНрдкрд░реНрдзреА .NET рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ

рдХреЗ рд▓рд┐рдП рдЖрд░реЗрдЦрдг 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, рдХреНрдпреЛрдВрдХрд┐ рд╕реА # рдореЗрдВ рдПрдХ рдкреНрд░рд╕рд┐рджреНрдз рд╣реИ 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), рдЬреЛ рд╕рднреА рд╡рд╕реНрддреБрдУрдВ рдореЗрдВ рдореМрдЬреВрдж рд╣реИрдВред рдЗрд╕рд▓рд┐рдП, рдпрджрд┐ рдХреЛрдИ рдЕрдиреБрдкрдпреБрдХреНрдд рд╡рд╕реНрддреБ рдХрд╛ рдЪрдпрди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдЖрдк рдЖрд╕рд╛рдиреА рд╕реЗ рдЧрддрд┐рд░реЛрдз рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рдЖрдк рдПрдХ рдЖрдВрддрд░рд┐рдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдкрд░ рд▓реЙрдХ рдХрд░рддреЗ рд╣реИрдВ)ред рд╣рдо рдЗрд╕рдХреЗ рд▓рд┐рдП рд╣рдореЗрд╢рд╛ рдЫреБрдкреА рд╣реБрдИ рд╡рд╕реНрддреБ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред

рдХрдВрдбреАрд╢рди рд╡реЗрд░рд┐рдПрдмрд▓ рдкреИрдЯрд░реНрди рдЖрдкрдХреЛ рдХреБрдЫ рдЬрдЯрд┐рд▓ рд╕реНрдерд┐рддрд┐ рдХреА рдЕрдкреЗрдХреНрд╖рд╛ рдХреЛ рдЕрдзрд┐рдХ рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред .NET рдореЗрдВ, рдореЗрд░реА рд░рд╛рдп рдореЗрдВ, рдпрд╣ рдЕрдзреВрд░рд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╕рд┐рджреНрдзрд╛рдВрдд рд░реВрдк рдореЗрдВ, рдХрдИ рдЪрд░ (рдкреЙрдЬрд╝рд┐рдХреНрд╕ рдереНрд░реЗрдбреНрд╕ рдореЗрдВ) рдкрд░ рдХрдИ рдХрддрд╛рд░реЗрдВ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП, рди рдХрд┐ рдПрдХ рд▓реЛрдХ рдкрд░ред рддрдм рдХреЛрдИ рдЙрдиреНрд╣реЗрдВ рд╕рднреА рджрд╛рд░реНрд╢рдирд┐рдХреЛрдВ рдХреЗ рд▓рд┐рдП рдмрдирд╛ рд╕рдХрддрд╛ рдерд╛ред рд▓реЗрдХрд┐рди рдЗрд╕ рд░реВрдк рдореЗрдВ рднреА, рдпрд╣ рдЖрдкрдХреЛ рдХреЛрдб рдХреЛ рдХрдо рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред

рдХрдИ рджрд╛рд░реНрд╢рдирд┐рдХ рдпрд╛ async / await

рдареАрдХ рд╣реИ, рдЕрдм рд╣рдо рдереНрд░реЗрдбреНрд╕ рдХреЛ рдкреНрд░рднрд╛рд╡реА рд░реВрдк рд╕реЗ рдмреНрд▓реЙрдХ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдЕрдЧрд░ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдмрд╣реБрдд рд╕рд╛рд░реЗ рджрд╛рд░реНрд╢рдирд┐рдХ рд╣реИрдВ? 100? 10000? рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рд╡реЗрдм рд╕рд░реНрд╡рд░ рд╕реЗ 100000 рдЕрдиреБрд░реЛрдз рдкреНрд░рд╛рдкреНрдд рд╣реБрдПред рдкреНрд░рддреНрдпреЗрдХ рдЕрдиреБрд░реЛрдз рдХреЗ рд▓рд┐рдП рдПрдХ рдереНрд░реЗрдб рдмрдирд╛рдирд╛ рдУрд╡рд░рд╣реЗрдб рд╣реЛрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рдЗрддрдиреЗ рд╕рд╛рд░реЗ рдзрд╛рдЧреЗ рд╕рдорд╛рдирд╛рдВрддрд░ рдореЗрдВ рдирд╣реАрдВ рдЪрд▓реЗрдВрдЧреЗред рдХреЗрд╡рд▓ рдЙрддрдиреЗ рд╣реА рдЪрд▓реЗрдВрдЧреЗ рдЬрд┐рддрдиреЗ рддрд╛рд░реНрдХрд┐рдХ рдХреЛрд░ рд╣реИрдВ (рдореЗрд░реЗ рдкрд╛рд╕ 4 рд╣реИрдВ)ред рдФрд░ рдмрд╛рдХреА рд╕рдм рд╕рд┐рд░реНрдл рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреЛ рдЫреАрди рд▓реЗрдВрдЧреЗред рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рдПрдХ рд╕рдорд╛рдзрд╛рди async/рдкреНрд░рддреАрдХреНрд╖рд╛ рдкреИрдЯрд░реНрди рд╣реИред рдЗрд╕рдХрд╛ рд╡рд┐рдЪрд╛рд░ рдпрд╣ рд╣реИ рдХрд┐ рдпрджрд┐ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреБрдЫ рдЬрд╛рд░реА рд░рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рддреЛ рдлрд╝рдВрдХреНрд╢рди рдереНрд░реЗрдб рдХреЛ рдирд╣реАрдВ рд░рдЦрддрд╛ рд╣реИред рдФрд░ рдЬрдм рдпрд╣ рдХреБрдЫ рдХрд░рддрд╛ рд╣реИ, рддреЛ рдпрд╣ рдЕрдкрдиреЗ рдирд┐рд╖реНрдкрд╛рджрди рдХреЛ рдлрд┐рд░ рд╕реЗ рд╢реБрд░реВ рдХрд░рддрд╛ рд╣реИ (рд▓реЗрдХрд┐рди рдЬрд░реВрд░реА рдирд╣реАрдВ рдХрд┐ рдЙрд╕реА рдзрд╛рдЧреЗ рдкрд░!) рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╣рдо рдХрд╛рдВрдЯреЗ рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░реЗрдВрдЧреЗред

SemaphoreSlim рдЗрд╕рдХреЗ рд▓рд┐рдП рд╣реИ WaitAsync() рддрд░реАрдХрд╛ред рдпрд╣рд╛рдБ рдЗрд╕ рдкреИрдЯрд░реНрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рдПрдХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИред

// ╨Ч╨░╨┐╤Г╤Б╨║ ╤В╨░╨║╨╛╨╣ ╨╢╨╡, ╨║╨░╨║ ╤А╨░╨╜╤М╤И╨╡. ╨У╨┤╨╡-╨╜╨╕╨▒╤Г╨┤╤М ╨▓ ╨┐╤А╨╛╨│╤А╨░╨╝╨╝╨╡:
Task.Run(() => Run(i, cancelTokenSource.Token));

// ╨Ч╨░╨┐╤Г╤Б╨║ ╤Д╨╕╨╗╨╛╤Б╨╛╤Д╨░.
// ╨Ъ╨╗╤О╤З╨╡╨▓╨╛╨╡ ╤Б╨╗╨╛╨▓╨╛ async -- ╨║╨╛╨╝╨┐╨╕╨╗╤П╤В╨╛╤А ╤В╤А╨░╨╜╤Б╨╗╨╕╤А╤Г╨╡╤В ╤Н╤В╨╛╤В ╨╝╨╡╤В╨╛╤В ╨▓ ╨░╤Б╨╕╨╜╤Е╤А╨╛╨╜╨╜╤Л╨╣.
public async Task Run(int i, CancellationToken token)
{
    while (true)
    {
        // await -- ╨▒╤Г╨┤╨╡╨╝ ╨╛╨╢╨╕╨┤╨░╤В╤М ╨║╨░╨║╨╛╨│╨╛-╤В╨╛ ╤Б╨╛╨▒╤Л╤В╨╕╤П.
        await TakeForks(i);
        // ╨Я╨╛╤Б╨╗╨╡ await, ╨┐╤А╨╛╨┤╨╛╨╗╨╢╨╡╨╜╨╕╨╡ ╨▓╨╛╨╖╨╝╨╛╨╢╨╜╨╛ ╨▓ ╨┤╤А╤Г╨│╨╛╨╝ ╨┐╨╛╤В╨╛╨║╨╡.
        eatenFood[i] = (eatenFood[i] + 1) % (int.MaxValue - 1);
        // ╨Ь╨╛╨╢╨╡╤В ╨▒╤Л╤В╤М ╨╜╨╡╤Б╨║╨╛╨╗╤М╨║╨╛ ╤Б╨╛╨▒╤Л╤В╨╕╨╣ ╨┤╨╗╤П ╨╛╨╢╨╕╨┤╨░╨╜╨╕╤П.
        await PutForks(i);

        Think(i);

        if (token.IsCancellationRequested) break;
    }
}

async Task TakeForks(int i)
{
    bool hasForks = false;
    while (!hasForks)
    {
        // ╨Т╨╖╨░╨╕╨╝╨╛╨╕╤Б╨║╨╗╤О╤З╨░╤О╤Й╨╕╨╣ ╨┤╨╛╤Б╤В╤Г╨┐ ╨║ ╤Б╤В╨╛╨╗╤Г:
        await _tableSemaphore.WaitAsync();
        if (forks[Left(i)] == 0 && forks[Right(i)] == 0)
        {
            forks[Left(i)] = i+1;
            forks[Right(i)] = i+1;
            hasForks = true;
        }
        _tableSemaphore.Release();
        // ╨С╤Г╨┤╨╡╨╝ ╨╛╨╢╨╕╨┤╨░╤В╤М, ╤З╤В╨╛╨▒╤Л ╤Б╨╛╤Б╨╡╨┤ ╨┐╨╛╨╗╨╛╨╢╨╕╨╗ ╨▓╨╕╨╗╨║╨╕:
        if (!hasForks)
            await _philosopherSemaphores[i].WaitAsync();
    }
}

// ╨Ц╨┤╨╡╨╝ ╨┤╨╛╤Б╤В╤Г╨┐╨░ ╨║ ╤Б╤В╨╛╨╗╤Г ╨╕ ╨║╨╗╨░╨┤╨╡╨╝ ╨▓╨╕╨╗╨║╨╕.
async Task PutForks(int i)
{
    await _tableSemaphore.WaitAsync();
    forks[Left(i)] = 0;
    // "╨Я╤А╨╛╨▒╤Г╨┤╨╕╤В╤М" ╤Б╨╛╤Б╨╡╨┤╨╡╨╣, ╨╡╤Б╨╗╨╕ ╨╛╨╜╨╕ "╤Б╨┐╨░╨╗╨╕".
    _philosopherSemaphores[LeftPhilosopher(i)].Release();
    forks[Right(i)] = 0;
    _philosopherSemaphores[RightPhilosopher(i)].Release();
    _tableSemaphore.Release();
}

рд╡рд┐рдзрд┐ рдХреЗ рд╕рд╛рде async / await рдПрдХ рдореБрд╢реНрдХрд┐рд▓ рд░рд╛рдЬреНрдп рдорд╢реАрди рдореЗрдВ рдЕрдиреБрд╡рд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬреЛ рддреБрд░рдВрдд рдЕрдкрдиреЗ рдЖрдВрддрд░рд┐рдХ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░ рджреЗрддрд╛ рд╣реИ Task. рдЗрд╕рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ, рдЖрдк рд╡рд┐рдзрд┐ рдХреЗ рдкреВрд░рд╛ рд╣реЛрдиреЗ рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЗрд╕реЗ рд░рджреНрдж рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдмрд╛рдХреА рд╕рдм рдХреБрдЫ рдЬреЛ рдЖрдк рдЯрд╛рд╕реНрдХ рдХреЗ рд╕рд╛рде рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд╡рд┐рдзрд┐ рдХреЗ рдЕрдВрджрд░, рд░рд╛рдЬреНрдп рдорд╢реАрди рдирд┐рд╖реНрдкрд╛рджрди рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рддреА рд╣реИред рд▓рдмреНрдмреЛрд▓реБрдЖрдм рдпрд╣ рд╣реИ рдХрд┐ рдпрджрд┐ рдХреЛрдИ рджреЗрд░реА рдирд╣реАрдВ рд╣реЛрддреА рд╣реИ, рддреЛ рдирд┐рд╖реНрдкрд╛рджрди рд╕рдордХрд╛рд▓рд┐рдХ рд╣реЛрддрд╛ рд╣реИ, рдФрд░ рдпрджрд┐ рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдереНрд░реЗрдб рдЬрд╛рд░реА рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕реЗ рдмреЗрд╣рддрд░ рдврдВрдЧ рд╕реЗ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕ рд╕реНрдЯреЗрдЯ рдорд╢реАрди рдХреЛ рджреЗрдЦрдирд╛ рдмреЗрд╣рддрд░ рд╣реЛрдЧрд╛ред рдЗрдирд╕реЗ рдЖрдк рдЪреЗрди рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ async / await рддрд░реАрдХреЗред

рдЪрд▓реЛ рдкрд░реАрдХреНрд╖рдг рдХрд░рддреЗ рд╣реИрдВред 100 рд▓реЙрдЬрд┐рдХрд▓ рдХреЛрд░, 4 рд╕реЗрдХрдВрдб рд╡рд╛рд▓реА рдорд╢реАрди рдкрд░ 8 рджрд╛рд░реНрд╢рдирд┐рдХреЛрдВ рдХрд╛ рдХрд╛рдоред рдореЙрдирд┐рдЯрд░ рдХреЗ рд╕рд╛рде рдкрд┐рдЫрд▓реЗ рд╕рдорд╛рдзрд╛рди рдиреЗ рдХреЗрд╡рд▓ рдкрд╣рд▓реЗ 4 рдзрд╛рдЧреЗ рдЪрд▓рд╛рдП рдФрд░ рдмрд╛рдХреА рдмрд┐рд▓реНрдХреБрд▓ рдирд╣реАрдВ рдЪрд▓реЗред рдЗрди 4 рдереНрд░реЗрдбреНрд╕ рдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рд▓рдЧрднрдЧ 2ms рдХреЗ рд▓рд┐рдП рдирд┐рд╖реНрдХреНрд░рд┐рдп рдерд╛ред рдФрд░ async / рдкреНрд░рддреАрдХреНрд╖рд╛ рд╕рдорд╛рдзрд╛рди рд╕рднреА 100 рдЪрд▓рд╛, рдкреНрд░рддреНрдпреЗрдХ 6.8 рд╕реЗрдХрдВрдб рдХреЗ рдФрд╕рдд рдкреНрд░рддреАрдХреНрд╖рд╛ рдХреЗ рд╕рд╛рдеред рдмреЗрд╢рдХ, рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдкреНрд░рдгрд╛рд▓рд┐рдпреЛрдВ рдореЗрдВ, 6 рд╕реЗрдХрдВрдб рдХреЗ рд▓рд┐рдП рдирд┐рд╖реНрдХреНрд░рд┐рдп рд╣реЛрдирд╛ рдЕрд╕реНрд╡реАрдХрд╛рд░реНрдп рд╣реИ рдФрд░ рдЗрд╕ рддрд░рд╣ рдХреЗ рдХрдИ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдирд╣реАрдВ рдХрд░рдирд╛ рдмреЗрд╣рддрд░ рд╣реИред рдореЙрдирд┐рдЯрд░ рд╡рд╛рд▓рд╛ рд╕рдорд╛рдзрд╛рди рдмрд┐рд▓реНрдХреБрд▓ рднреА рдорд╛рдкрдиреАрдп рдирд╣реАрдВ рдирд┐рдХрд▓рд╛ред

рдирд┐рд╖реНрдХрд░реНрд╖

рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдЗрди рдЫреЛрдЯреЗ рдЙрджрд╛рд╣рд░рдгреЛрдВ рд╕реЗ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, .NET рдХрдИ рддреБрд▓реНрдпрдХрд╛рд▓рди рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдпрд╣ рд╣рдореЗрд╢рд╛ рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ рдХрд┐ рдЙрдирдХрд╛ рдЙрдкрдпреЛрдЧ рдХреИрд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рдПред рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдпрд╣ рд▓реЗрдЦ рдорджрджрдЧрд╛рд░ рдерд╛ред рдЕрднреА рдХреЗ рд▓рд┐рдП, рдпрд╣ рдЕрдВрдд рд╣реИ, рд▓реЗрдХрд┐рди рдЕрднреА рднреА рдмрд╣реБрдд рд╕реА рджрд┐рд▓рдЪрд╕реНрдк рдЪреАрдЬреЗрдВ рдмрд╛рдХреА рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдереНрд░реЗрдб-рд╕реБрд░рдХреНрд╖рд┐рдд рд╕рдВрдЧреНрд░рд╣, рдЯреАрдкреАрдПрд▓ рдбреЗрдЯрд╛рдлреНрд▓реЛ, рд░рд┐рдПрдХреНрдЯрд┐рд╡ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ, рд╕реЙрдлреНрдЯрд╡реЗрдпрд░ рд▓реЗрдирджреЗрди рдореЙрдбрд▓, рдЖрджрд┐ред

рд╕реВрддреНрд░реЛрдВ рдХрд╛ рдХрд╣рдирд╛ рд╣реИ

рд╕реНрд░реЛрдд: www.habr.com

рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдЬреЛрдбрд╝реЗрдВ