zoukankan      html  css  js  c++  java
  • c# Thread Synchronization

    Introduce a question

    Consider the follow code snippet:

     1 class Program
     2     {
     3         static int _hours = 0;
     4 
     5         static void Main(string[] args)
     6         {
     7             var tasks = new Task[2];
     8             for (int i = 0; i < tasks.Length; i++)
     9             {
    10                 tasks[i] = new Task(Work);
    11                 tasks[i].Start();
    12             }
    13 
    14             for (int i = 0; i < tasks.Length; i++)
    15             {
    16                 tasks[i].Wait();
    17             }
    18 
    19             Console.WriteLine(_hours);
    20         }
    21 
    22         static void Work()
    23         {
    24             for (int i = 0; i < 8; i++)
    25             {
    26                 Thread.Sleep(10);
    27                 _hours += 1;
    28                 Console.WriteLine("task:{0},nth:{1},hours:{2}", Thread.CurrentThread.ManagedThreadId, i, _hours);
    29             }
    30         }
    31     }
    View Code Detail

    The run resut of above code is:

    task:4,nth:0,hours:1
    task:3,nth:0,hours:2
    task:4,nth:1,hours:3
    task:3,nth:1,hours:4
    task:4,nth:2,hours:6
    task:3,nth:2,hours:6
    task:4,nth:3,hours:7
    task:3,nth:3,hours:7
    task:4,nth:4,hours:9
    task:3,nth:4,hours:9
    task:3,nth:5,hours:10
    task:4,nth:5,hours:11
    task:3,nth:6,hours:13
    task:4,nth:6,hours:13
    task:3,nth:7,hours:15
    task:4,nth:7,hours:15
    15
    Press any key to continue . . .
    View Code

    Please observe the values of hours, and it's final value is 15 instead of 16.

    From bussiness perspective, each task works 8 hours, so two tasks should work 16 hours. But the result is 15, why?

    Solve the question

      The problem is caused by Thread Synchronization.

      We can resolve it using Synchronization technique.

      1. Using Lock

     1 class Program
     2     {
     3         static int _hours = 0;
     4         static object _synRoot = new object();
     5 
     6         static void Main(string[] args)
     7         {
     8             var tasks = new Task[2];
     9             for (int i = 0; i < tasks.Length; i++)
    10             {
    11                 tasks[i] = new Task(Work);
    12                 tasks[i].Start();
    13             }
    14 
    15             for (int i = 0; i < tasks.Length; i++)
    16             {
    17                 tasks[i].Wait();
    18             }
    19 
    20             Console.WriteLine(_hours);
    21         }
    22 
    23         static void Work()
    24         {
    25             for (int i = 0; i < 8; i++)
    26             {
    27                 Thread.Sleep(10);
    28                 lock (_synRoot)
    29                 {
    30                     _hours += 1;
    31                 }
    32                 Console.WriteLine("task:{0},nth:{1},hours:{2}", Thread.CurrentThread.ManagedThreadId, i, _hours);
    33             }
    34         }
    35     }
    View Code

    The run resut of above code is:

    task:3,nth:0,hours:2
    task:4,nth:0,hours:2
    task:4,nth:1,hours:3
    task:3,nth:1,hours:4
    task:3,nth:2,hours:5
    task:4,nth:2,hours:6
    task:3,nth:3,hours:7
    task:4,nth:3,hours:8
    task:4,nth:4,hours:9
    task:3,nth:4,hours:10
    task:4,nth:5,hours:11
    task:3,nth:5,hours:12
    task:3,nth:6,hours:14
    task:4,nth:6,hours:14
    task:4,nth:7,hours:15
    task:3,nth:7,hours:16
    16
    Press any key to continue . . .
    View Code

      As the result shown, we get the correct value 16 now.

    2. Using Interlocked

    class Program
        {
            static int _hours = 0;
            static object _synRoot = new object();
    
            static void Main(string[] args)
            {
                var tasks = new Task[2];
                for (int i = 0; i < tasks.Length; i++)
                {
                    tasks[i] = new Task(Work);
                    tasks[i].Start();
                }
    
                for (int i = 0; i < tasks.Length; i++)
                {
                    tasks[i].Wait();
                }
    
                Console.WriteLine(_hours);
            }
    
            static void Work()
            {
                for (int i = 0; i < 8; i++)
                {
                    Thread.Sleep(10);
                    Interlocked.Increment(ref _hours);
                    //_hours++; Using this statement may result in an unexpected value.
                    Console.WriteLine("task:{0},nth:{1},hours:{2}", Thread.CurrentThread.ManagedThreadId, i, _hours);
                }
            }
        }
    View Code

    The run resut of above code is:

    task:5,nth:0,hours:1
    task:3,nth:0,hours:2
    task:3,nth:1,hours:4
    task:5,nth:1,hours:4
    task:5,nth:2,hours:5
    task:3,nth:2,hours:6
    task:5,nth:3,hours:7
    task:3,nth:3,hours:8
    task:3,nth:4,hours:9
    task:5,nth:4,hours:10
    task:5,nth:5,hours:12
    task:3,nth:5,hours:12
    task:5,nth:6,hours:13
    task:3,nth:6,hours:14
    task:3,nth:7,hours:15
    task:5,nth:7,hours:16
    16
    Press any key to continue . . .
    View Code
  • 相关阅读:
    Swiper 自定义分页器 并实现多个用省略号显示
    Swiper插件 滚动自动切换标题
    HTML 点击返回按钮返回上一页,没有上一页转到首页
    HTML input 模仿Android原生焦点效果
    HTML基础篇(二、HTML文档结构)
    Vue开发 添加微信分享功能(全局分享)
    JS 命令模式(记读《JavaScript设计模式与开发实践》笔记)
    Vue中v-for配合使用Swiper插件问题
    permission-sudo获取权限
    使用es6模块化后打开页面报错
  • 原文地址:https://www.cnblogs.com/cnbwang/p/3651706.html
Copyright © 2011-2022 走看看