码迷,mamicode.com
首页 > 编程语言 > 详细

线程、任务和同步学习笔记(五)

时间:2016-06-06 13:43:47      阅读:173      评论:0      收藏:0      [点我收藏+]

标签:

1、如果两个或多个线程访问相同的对象,或者访问不同步的共享状态,会出现争用条件。

 1 using System;
 2 using System.Threading;
 3 
 4 class Outputer
 5 {
 6     public void Output(string msg)
 7     {
 8         for (int i = 0; i < msg.Length; i++)
 9         {
10             Console.Write(msg[i]);
11         }
12         Console.WriteLine();
13     }
14 }
15 
16 class Program
17 {
18     static void Main(string[] args)
19     {
20         Outputer outputer = new Outputer();
21         object locker = new object();
22         new Thread((msg) =>
23         {
24             while (true)
25             {
26                 outputer.Output(msg.ToString());
27             }
28         }).Start("abcdef");
29         new Thread(() =>
30         {
31             while (true)
32             {
33                 outputer.Output("1234567890");
34             }
35         }).Start();
36     }
37 }

运行结果:

技术分享

2、要避免该问题,可以使用lock语句锁定共享的对象。

 1 using System;
 2 using System.Threading;
 3 
 4 class Outputer
 5 {
 6     public void Output(string msg)
 7     {
 8         for (int i = 0; i < msg.Length; i++)
 9         {
10             Console.Write(msg[i]);
11         }
12         Console.WriteLine();
13     }
14 }
15 
16 class Program
17 {
18     static void Main(string[] args)
19     {
20         Outputer outputer = new Outputer();
21         object locker = new object();
22         new Thread((msg) =>
23         {
24             while (true)
25             {
26                 lock (locker)
27                 {
28                     outputer.Output(msg.ToString());
29                 }
30             }
31         }).Start("abcdef");
32         new Thread(() =>
33         {
34             while (true)
35             {
36                 lock (locker)
37                 {
38                     outputer.Output("1234567890");
39                 }
40             }
41         }).Start();
42     }
43 }

运行结果:

技术分享

3、也可以将共享对象设置为线程安全的对象。

 1 using System;
 2 using System.Threading;
 3 
 4 class Outputer
 5 {
 6     object locker = new object();
 7 
 8     public void Output(string msg)
 9     {
10         lock (locker)
11         {
12             for (int i = 0; i < msg.Length; i++)
13             {
14                 Console.Write(msg[i]);
15             }
16             Console.WriteLine();
17         }
18     }
19 }
20 
21 class Program
22 {
23     static void Main(string[] args)
24     {
25         Outputer outputer = new Outputer();
26         new Thread((msg) =>
27         {
28             while (true)
29             {
30                 
31                 outputer.Output(msg.ToString());
32             }
33         }).Start("abcdef");
34         new Thread(() =>
35         {
36             while (true)
37             {
38                 
39                 outputer.Output("1234567890");
40             }
41         }).Start();
42     }
43 }

4、过多的锁定会造成死锁。所谓死锁即是至少有两个线程被挂起,互相等待对方解锁,以至于线程无限等待下去。

 1 using System;
 2 using System.Threading;
 3 
 4 class DeadLocker
 5 {
 6     object locker1 = new object();
 7     object locker2 = new object();
 8 
 9     public void Method1()
10     {
11         while (true)
12         {
13             lock (locker1)
14             {
15                 lock (locker2)
16                 {
17                     Console.WriteLine("First lock1, and then lock2");
18                 }
19             }
20         }
21     }
22 
23     public void Method2()
24     {
25         while (true)
26         {
27             lock (locker2)
28             {
29                 lock (locker1)
30                 {
31                     Console.WriteLine("First lock2, and then lock1");
32                 }
33             }
34         }
35     }
36 }
37 
38 class Program
39 {
40     static void Main(string[] args)
41     {
42         DeadLocker dl = new DeadLocker();
43         new Thread(dl.Method1).Start();
44         new Thread(dl.Method2).Start();
45     }
46 }

运行结果:

技术分享

5、同步问题和争用条件以及死锁相关,要避免同步问题,最好就不要在线程之间共享数据。如果要共享数据就必须使用同步技术,确保一次只有一个线程访问和改变共享状态。在C#中,lock语句是设置锁定和解除锁定的一种简单方式。编译器将其编译为IL后,会被编译成了调用Monitor类的Enter和Exit方法。

 1 using System;
 2 using System.Threading;
 3 
 4 class Program
 5 {
 6     static void Main(string[] args)
 7     {
 8     }
 9 
10     void Method()
11     {
12         lock (typeof(Program))
13         {
14         }
15     }
16 }

编译结果:

技术分享

6、争用条件的另一个例子。

 1 using System;
 2 using System.Threading;
 3 using System.Threading.Tasks;
 4 
 5 class SharedState
 6 {
 7     public int State { get; set; }
 8 }
 9 
10 class Worker
11 {
12     SharedState state;
13 
14     public Worker(SharedState state)
15     {
16         this.state = state;
17     }
18 
19     public void DoJob()
20     {
21         for (int i = 0; i < 500; i++)
22         {
23             state.State += 1;
24         }
25     }
26 }
27 
28 class Program
29 {
30     static void Main(string[] args)
31     {
32         int numTasks = 20;
33         var state = new SharedState();
34         var tasks = new Task[numTasks];
35         for (int i = 0; i < numTasks; i++)
36         {
37             tasks[i] = new Task(new Worker(state).DoJob);
38             tasks[i].Start();
39         }
40         for (int i = 0; i < numTasks; i++)
41         {
42             tasks[i].Wait(); //使20个任务全部处于等待状态,直到所有任务都执行完毕为止
43         }
44         Console.WriteLine("Summarized {0}", state.State);
45     }
46 }

运行结果:

技术分享

从上面结果看出,20个任务分别对共享的数据累加后,打印其结果。每个任务执行500次,共20个任务,理想的结果是10000,但是事实并非如此。

线程、任务和同步学习笔记(五)

标签:

原文地址:http://www.cnblogs.com/luckymonkey/p/5563479.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!