c# Thread Synchronization

Introduce a question

Consider the follow code snippet:ide

 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:this

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.spa

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

 

Solve the question

  The problem is caused by Thread Synchronization.code

  We can resolve it using Synchronization technique.blog

  1. Using Lockip

 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:rem

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.get

 

2. Using Interlockedstring

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
相關文章
相關標籤/搜索