рд░рд╛рдореНрд░реЛ-рдлреЗрдб рджрд╛рд░реНрд╢рдирд┐рдХ рд╡рд╛ рдкреНрд░рддрд┐рд╕реНрдкрд░реНрдзреА .NET рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ

рд░рд╛рдореНрд░реЛ-рдлреЗрдб рджрд╛рд░реНрд╢рдирд┐рдХ рд╡рд╛ рдкреНрд░рддрд┐рд╕реНрдкрд░реНрдзреА .NET рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ

.Net рдорд╛ рд╕рдорд╡рд░реНрддреА рд░ рд╕рдорд╛рдирд╛рдиреНрддрд░ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдЩрд▓реЗ рдХрд╕рд░реА рдХрд╛рдо рдЧрд░реНрдЫ рд╣реЗрд░реМрдВ, рдЙрджрд╛рд╣рд░рдгрдХреЛ рд░реВрдкрдорд╛ Philosophers Dining Problem рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░ред рдпреЛрдЬрдирд╛ рдпреЛ рд╣реЛ, рдереНрд░реЗрдбрд╣рд░реВ / рдкреНрд░рдХреНрд░рд┐рдпрд╛рд╣рд░реВрдХреЛ рд╕рд┐рдВрдХреНрд░реЛрдирд╛рдЗрдЬреЗрд╕рдирдмрд╛рдЯ, рдЕрднрд┐рдиреЗрддрд╛ рдореЛрдбреЗрд▓рдорд╛ (рдирд┐рдореНрди рднрд╛рдЧрд╣рд░реВрдорд╛)ред рд▓реЗрдЦ рдкрд╣рд┐рд▓реЛ рдкрд░рд┐рдЪрд┐рддрдХреЛ рд▓рд╛рдЧрд┐ рд╡рд╛ рддрдкрд╛рдИрдВрдХреЛ рдЬреНрдЮрд╛рди рддрд╛рдЬрд╛ рдЧрд░реНрдирдХреЛ рд▓рд╛рдЧрд┐ рдЙрдкрдпреЛрдЧреА рд╣реБрди рд╕рдХреНрдЫред

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

рдереНрд░реЗрдб рдкреВрд▓ рдереНрд░реЗрдб рдирд┐рд░реНрдорд╛рдг рд░ рдореЗрдЯрд╛рдЙрдиреЗ рдЕрдиреБрдХреВрд▓рди рдЧрд░реНрди рдбрд┐рдЬрд╛рдЗрди рдЧрд░рд┐рдПрдХреЛ рдЫред рдпреЛ рдкреЛрдЦрд░реАрдорд╛ рдХрд╛рд░реНрдпрд╣рд░реВ рд╕рд╣рд┐рддрдХреЛ рд▓рд╛рдо рдЫ рд░ CLR рд▓реЗ рдпреА рдХрд╛рд░реНрдпрд╣рд░реВрдХреЛ рд╕рдЩреНрдЦреНрдпрд╛рдХреЛ рдЖрдзрд╛рд░рдорд╛ рдереНрд░реЗрдбрд╣рд░реВ рд╕рд┐рд░реНрдЬрдирд╛ рд╡рд╛ рд╣рдЯрд╛рдЙрдБрдЫред рд╕рдмреИ 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)
    );
}

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

рд░рд╛рдореНрд░реЛ-рдлреЗрдб рджрд╛рд░реНрд╢рдирд┐рдХ рд╡рд╛ рдкреНрд░рддрд┐рд╕реНрдкрд░реНрдзреА .NET рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ

рдпрд╣рд╛рдБ рддрдкрд╛рдИрдВрд▓реЗ рджреЗрдЦреНрди рд╕рдХреНрдиреБрд╣реБрдиреНрдЫ рдХрд┐ рдереНрд░реЗрдбрд╣рд░реВ рдХрд╣рд┐рд▓реЗрдХрд╛рд╣реАрдБ рдЙрдареНрдЫрдиреН рд░ рд╕реНрд░реЛрдд рдкреНрд░рд╛рдкреНрдд рдЧрд░реНрдиреЗ рдкреНрд░рдпрд╛рд╕ рдЧрд░реНрдЫрдиреНред рдЪрд╛рд░ рдХреЛрд░ рдордзреНрдпреЗ рджреБрдИрд▓реЗ рдХреЗрд╣реА рдЧрд░реНрджреИрдирдиреН (рдорд╛рдерд┐рдХреЛ рд╣рд░рд┐рдпреЛ рдЧреНрд░рд╛рдл)ред

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

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

рд░рд╛рдореНрд░реЛ-рдлреЗрдб рджрд╛рд░реНрд╢рдирд┐рдХ рд╡рд╛ рдкреНрд░рддрд┐рд╕реНрдкрд░реНрдзреА .NET рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ

рдХреЛ рд▓рд╛рдЧреА рд░реЗрдЦрд╛рдЪрд┐рддреНрд░ SpinLockред рд╕реНрдЯреНрд░рд┐рдорд╣рд░реВ рд╕реБрдиреМрд▓реЛ рдХрд╛рдБрдЯрд╛рдХреЛ рд▓рд╛рдЧрд┐ рдирд┐рд░рдиреНрддрд░ "рд▓рдбрд╛рдЗрдБ" рдЫрдиреНред рддреНрдпрд╣рд╛рдБ рд╡рд┐рдлрд▓рддрд╛рд╣рд░реВ рдЫрдиреН - рдЪрд┐рддреНрд░рдорд╛, рдЪрдпрди рдЧрд░рд┐рдПрдХреЛ рдХреНрд╖реЗрддреНрд░ред рдХреЛрд░рд╣рд░реВ рдкреВрд░реНрдг рд░реВрдкрдорд╛ рдкреНрд░рдпреЛрдЧ рдЧрд░рд┐рдПрдХрд╛ рдЫреИрдирдиреН: рдпреА рдЪрд╛рд░ рдереНрд░реЗрдбрд╣рд░реВрджреНрд╡рд╛рд░рд╛ рдорд╛рддреНрд░ 2/3ред

рдЕрд░реНрдХреЛ рд╕рдорд╛рдзрд╛рди рдпрд╣рд╛рдБ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрди рдорд╛рддреНрд░ рд╣реБрдиреЗрдЫ Interlocked.CompareExchange рдорд╛рдерд┐рдХреЛ рдХреЛрдбрдорд╛ рджреЗрдЦрд╛рдЗрдП рдЬрд╕реНрддреИ рд╕рдХреНрд░рд┐рдп рдкрд░реНрдЦрд╛рдЗрдХреЛ рд╕рд╛рде (рднреЛрдХрд▓реЗ рдорд░реЗрдХрд╛ рджрд╛рд░реНрд╢рдирд┐рдХрд╣рд░реВрдорд╛), рддрд░ рдпреЛ, рдкрд╣рд┐рд▓реЗ рдиреИ рднрдирд┐рдПрдЭреИрдВ, рд╕реИрджреНрдзрд╛рдиреНрддрд┐рдХ рд░реВрдкрдорд╛ рдЕрд╡рд░реБрджреНрдз рд╣реБрди рд╕рдХреНрдЫред

рдмрд╛рд░реЗрдорд╛ Interlocked рдпреЛ рдзреНрдпрд╛рди рджрд┐рдиреБрдкрд░реНрдЫ рдХрд┐ рддреНрдпрд╣рд╛рдБ рдорд╛рддреНрд░ рдЫреИрди CompareExchange, рддрд░ рдкрд░рдорд╛рдгреБ рдкрдвреНрди рд░ рд▓реЗрдЦреНрдирдХрд╛ рд▓рд╛рдЧрд┐ рдЕрдиреНрдп рд╡рд┐рдзрд┐рд╣рд░реВ рдкрдирд┐ред рд░ рдкрд░рд┐рд╡рд░реНрддрдирдХреЛ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдорд╛рд░реНрдлрдд, рдпрджрд┐ рдЕрд░реНрдХреЛ рдереНрд░реЗрдбрдорд╛ рдкрд░рд┐рд╡рд░реНрддрдирд╣рд░реВ рдЧрд░реНрди рд╕рдордп рдЫ рднрдиреЗ (рдкрдвреНрдиреБрд╣реЛрд╕реН 1, рдкрдвреНрдиреБрд╣реЛрд╕реН 2, рд▓реЗрдЦреНрдиреБрд╣реЛрд╕реН 2, рд▓реЗрдЦреНрдиреБрд╣реЛрд╕реН 1 рдЦрд░рд╛рдм рдЫ), рдпрд╕рд▓рд╛рдИ рдПрдХрд▓ рдорд╛рдирдорд╛ рдЬрдЯрд┐рд▓ рдкрд░рд┐рд╡рд░реНрддрдирд╣рд░реВрдХреЛ рд▓рд╛рдЧрд┐ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрди рд╕рдХрд┐рдиреНрдЫ (рдЗрдиреНрдЯрд░рд▓рдХ рдЧрд░рд┐рдПрдХреЛ рдХреБрдиреИ рдкрдирд┐ рдврд╛рдБрдЪрд╛)ред ред

рдХрд░реНрдиреЗрд▓ рдореЛрдб рд╕рдорд╛рдзрд╛рди

рд▓реВрдкрдорд╛ рд╕реНрд░реЛрддрд╣рд░реВ рдмрд░реНрдмрд╛рдж рд╣реБрдирдмрд╛рдЯ рдЬреЛрдЧрд┐рди, рд╣рд╛рдореА рдХрд╕рд░реА рдереНрд░реЗрдб рдмреНрд▓рдХ рдЧрд░реНрди рд╕рдХреНрдЫреМрдВ рд╣реЗрд░реМрдВред рдЕрд░реНрдХреЛ рд╢рдмреНрджрдорд╛, рд╣рд╛рдореНрд░реЛ рдЙрджрд╛рд╣рд░рдг рдЬрд╛рд░реА рд░рд╛рдЦреНрджреИ, рд╣реЗрд░реМрдВ рдХрд┐ рдХрд╕рд░реА рд╡реЗрдЯрд░рд▓реЗ рджрд╛рд░реНрд╢рдирд┐рдХрд▓рд╛рдИ рд╕реБрддреНрдЫ рд░ рдЖрд╡рд╢реНрдпрдХ рдкрд░реНрджрд╛ рдорд╛рддреНрд░ рдЙрд╕рд▓рд╛рдИ рдЙрдард╛рдЙрдБрдЫред рдкрд╣рд┐рд▓реЗ, рдЕрдкрд░реЗрдЯрд┐рдЩ рд╕рд┐рд╕реНрдЯрдордХреЛ рдХрд░реНрдиреЗрд▓ рдореЛрдб рдорд╛рд░реНрдлрдд рдпреЛ рдХрд╕рд░реА рдЧрд░реНрдиреЗ рднрдиреЗрд░ рд╣реЗрд░реМрдВред рддреНрдпрд╣рд╛рдБ рд╕рдмреИ рд╕рдВрд░рдЪрдирд╛рд╣рд░реВ рдкреНрд░рд╛рдпрдГ рдкреНрд░рдпреЛрдЧрдХрд░реНрддрд╛ рд╕реНрдкреЗрд╕рдорд╛ рднрдПрдХрд╛ рд╕рдВрд░рдЪрдирд╛рд╣рд░реВ рднрдиреНрджрд╛ рдврд┐рд▓реЛ рд╣реБрдиреНрдЫрдиреНред рдЙрджрд╛рд╣рд░рдгрдХрд╛ рд▓рд╛рдЧрд┐, рдзреЗрд░реИ рдкрдЯрдХ рдврд┐рд▓реЛ AutoResetEvent рд╕рд╛рдпрдж релрей рдЧреБрдгрд╛ рдврд┐рд▓реЛ SpinLock [рд░рд┐рдХреНрдЯрд░]ред рддрд░ рддрд┐рдиреАрд╣рд░реВрдХреЛ рдорджреНрджрддрд▓реЗ, рддрдкрд╛рдЗрдБ рдкреНрд░рдгрд╛рд▓реАрдорд╛ рдкреНрд░рдХреНрд░рд┐рдпрд╛рд╣рд░реВ рд╕рд┐рдЩреНрдХреНрд░реЛрдирд╛рдЗрдЬ рдЧрд░реНрди рд╕рдХреНрдиреБрд╣реБрдиреНрдЫ, рд╡реНрдпрд╡рд╕реНрдерд┐рдд рд╡рд╛ рд╣реЛрдЗрдиред

рдпрд╣рд╛рдБрдХреЛ рдЖрдзрд╛рд░рднреВрдд рдирд┐рд░реНрдорд╛рдг рдЖрдзрд╛ рд╢рддрд╛рдмреНрджреА рдЕрдШрд┐ рдбрд┐рдЬреНрдХрд╕реНрдЯреНрд░рд╛рд▓реЗ рдкреНрд░рд╕реНрддрд╛рд╡ рдЧрд░реЗрдХреЛ рд╕реЗрдорд╛рдлреЛрд░ рд╣реЛред рд╕реЗрдорд╛рдлреЛрд░ рднрдиреЗрдХреЛ рдкреНрд░рдгрд╛рд▓реАрджреНрд╡рд╛рд░рд╛ рд╡реНрдпрд╡рд╕реНрдерд┐рдд рдЧрд░рд┐рдПрдХреЛ рд╕рдХрд╛рд░рд╛рддреНрдордХ рдкреВрд░реНрдгрд╛рдВрдХ рд╣реЛ, рд░ рдпрд╕рдорд╛ рджреБрдИрд╡рдЯрд╛ рдЕрдкрд░реЗрд╢рдирд╣рд░реВ рд╡реГрджреНрдзрд┐ рд░ рдШрдЯрд╛рдЗ рд╣реБрдиреНрдЫред рдпрджрд┐ рдпреЛ рдШрдЯрд╛рдЙрди рдЕрд╕рдлрд▓ рднрдпреЛ рднрдиреЗ, рд╢реВрдиреНрдп, рддреНрдпрд╕рдкрдЫрд┐ рдХрд▓рд┐рдЩ рдереНрд░реЗрдб рдЕрд╡рд░реБрджреНрдз рдЫред рдЬрдм рд╕рдВрдЦреНрдпрд╛ рдХреЗрд╣реА рдЕрдиреНрдп рд╕рдХреНрд░рд┐рдп рдереНрд░реЗрдб/рдкреНрд░рдХреНрд░рд┐рдпрд╛рджреНрд╡рд╛рд░рд╛ рдмрдврд╛рдЗрдиреНрдЫ, рддрдм рдереНрд░реЗрдбрд╣рд░реВ рдЫреЛрдбрд┐рдиреНрдЫрдиреН рд░ рд╕реЗрдорд╛рдлреЛрд░ рдлреЗрд░рд┐ рдкрд╛рд╕ рдЧрд░рд┐рдПрдХреЛ рд╕рдВрдЦреНрдпрд╛рджреНрд╡рд╛рд░рд╛ рдШрдЯрд╛рдЗрдиреНрдЫред рдПрдХ рд╕реЗрдорд╛рдлреЛрд░ рд╕рдВрдЧ рдПрдХ рдмрд╛рдзрд╛ рдорд╛ рдЯреНрд░реЗрди рдХреЛ рдХрд▓реНрдкрдирд╛ рдЧрд░реНрди рд╕рдХреНрдиреБрд╣реБрдиреНрдЫред .NET рд▓реЗ рд╕рдорд╛рди рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛рдХрд╛ рд╕рд╛рде рдзреЗрд░реИ рдирд┐рд░реНрдорд╛рдгрд╣рд░реВ рдкреНрд░рджрд╛рди рдЧрд░реНрджрдЫ: AutoResetEvent, ManualResetEvent, Mutex рд░ рдо Semaphoreред рд╣рд╛рдореА рдкреНрд░рдпреЛрдЧ рдЧрд░реНрдиреЗрдЫреМрдВ AutoResetEvent, рдпреЛ рдпреА рдирд┐рд░реНрдорд╛рдгрд╣рд░реВ рдордзреНрдпреЗ рд╕рд░рд▓ рдЫ: рдХреЗрд╡рд▓ рджреБрдИ рдорд╛рдирд╣рд░реВ 0 рд░ 1 (рдЭреВрдЯреЛ, рд╕рддреНрдп)ред рдЙрдирдХреЛ рд╡рд┐рдзрд┐ WaitOne() рдпрджрд┐ рдорд╛рди реж рдерд┐рдпреЛ рднрдиреЗ рдХрд▓рд┐рдЩ рдереНрд░реЗрдбрд▓рд╛рдИ рд░реЛрдХреНрдЫ, рд░ рдпрджрд┐ рез, рдпрд╕рд▓рд╛рдИ реж рдорд╛ рдШрдЯрд╛рдЙрдБрдЫ рд░ рдпрд╕рд▓рд╛рдИ рдЫреЛрдбреНрдЫред рдПрдХ рд╡рд┐рдзрд┐ 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) рдХреЛ рдЕрдзрд┐рдХрддрдо рдорд╛рди рднрдПрдХреЛ рд╕рдорд╛рди рд╕реЗрдорд╛рдлреЛрд░ рд╣реЛ, рддрд░ рд▓реВрдк, рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐, рдХрдиреНрдбрд┐рд╢рди рднреЗрд░рд┐рдПрдмрд▓ рдврд╛рдБрдЪрд╛ (рддрд▓рдХреЛ рдмрд╛рд░реЗрдорд╛ рдердк), рдЖрджрд┐рдорд╛ рдкрд░реНрдЦрди рд╕рдорд░реНрдерди рд╕рд╣рд┐рддред рдпрд╕рдХреЛ рд╕рдорд╛рдзрд╛рди рд╣реЗрд░реМрдВред

// ╨б╨┐╤А╤П╤З╨╡╨╝ ╨╛╨▒╤К╨╡╨║╤В ╨┤╨╗╤П ╨Ь╨╛╨╜╨╕╤В╨╛╤А╨░ ╨╛╤В ╨▓╤Б╨╡╤Е, ╤З╤В╨╛╨▒╤Л ╨▒╨╡╨╖ ╨┤╨╡╨┤╨╗╨╛╨║╨╛╨▓.
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 рдЫ)ред рд░ рдЕрд░реВ рд╕рдмреИрд▓реЗ рдорд╛рддреНрд░ рд╕реНрд░реЛрддрд╣рд░реВ рд▓рд┐рдиреЗрдЫрдиреНред рдпрд╕ рд╕рдорд╕реНрдпрд╛рдХреЛ рдПрдХ рд╕рдорд╛рдзрд╛рди 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/await solution рд╕рдмреИ 100 рджреМрдбрд┐рдпреЛ, рдкреНрд░рддреНрдпреЗрдХ 6.8 рд╕реЗрдХреЗрдиреНрдбрдХреЛ рдФрд╕рдд рдкрд░реНрдЦрд╛рдЗрдХреЛ рд╕рд╛рдеред рдирд┐рд╕реНрд╕рдиреНрджреЗрд╣, рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдкреНрд░рдгрд╛рд▓реАрд╣рд░реВрдорд╛, 6 рд╕реЗрдХреЗрдиреНрдбрдХреЛ рд▓рд╛рдЧрд┐ рдирд┐рд╖реНрдХреНрд░рд┐рдп рдЕрд╕реНрд╡реАрдХрд╛рд░реНрдп рдЫ рд░ рдпреЛ рдЬрд╕реНрддреИ рдзреЗрд░реИ рдЕрдиреБрд░реЛрдзрд╣рд░реВ рдкреНрд░рд╢реЛрдзрди рдирдЧрд░реНрдиреБ рд░рд╛рдореНрд░реЛ рдЫред рдореЛрдирд┐рдЯрд░рдХреЛ рд╕рд╛рде рд╕рдорд╛рдзрд╛рди рд╕рдмреИ рд╕реНрдХреЗрд▓реЗрдмрд▓ рд╣реБрди рд╕рдХреЗрдиред

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

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

рд╕реНрд░реЛрддрд╣рд░реВ

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

рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдердкреНрди