线程同步傻问题:该被同步的变量没有用信号量控制,值是否会被改变
线程同步傻问题:该被同步的变量没有用信号量控制,值是否会被改变
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading;
6
7 namespace testLockList
8 {
9 class Program
10 {
11
12 const int ThreadMaxNum = 5; //要启动的线程的最大数目
13 static void Main(string[] args)
14 {
15 TestList myList = new TestList();
16 for (int i = 0; i < ThreadMaxNum; i++)//同时建立ThreadMaxNum个进程,
17 { //调用Add方法,看锁住了List,是否能对List里面的单个元素进行修改
18 Thread myth = new Thread(TestList.add);
19 myth.Name = string.Format("线程{0}", i);
20 myth.IsBackground = true;
21 myth.Start();
22 }
23 while (TestList.AddInvokeCount != 5)
24 {
25 Thread.Sleep(500);
26 }
27
28 }
29 }
30
31 public class TestList
32 {
33 static List<tester> myList = new List<tester>();//一个List
34 public static int AddInvokeCount = 0; //用于记录Add被调用的次数
35 public TestList()
36 {
37 myList.Add(new tester(0, 0)); //保证第一个元素有值,为了后面取出第一个元素不出错
38 }
39 /// <summary>
40 /// 这个方法用来测试,被锁住的List是否可以被改变值,如果changeValue方法里面没有进行同步
41 /// </summary>
42 static public void changeValue()
43 {
44 tester valueToChange = myList[0];//取出第一个元素
45 valueToChange.a = 111; //这里改变List中元素的值
46 Console.WriteLine(string.Format("第一个元素被改变的值:{0}",valueToChange.a));
47 }
48 static public void add()
49 {
50 lock (myList)
51 {
52 int Num = myList.Count + 1;
53 Thread.Sleep(1000); //保证线程等待
54 myList.Add(new tester(Num, Num));
55 if (AddInvokeCount == 1) //在myMutex未被释放的情况下,changeValue函数里面没有用信号量进行访问控制,
56 { //用另一个线程执行changeValue,看是否可以访问被信号量锁住的变量。
57 Thread changeValueThread = new Thread(TestList.changeValue);
58 changeValueThread.Start();
59 Console.WriteLine("线程等待3秒,保证myList被锁住");
60 Thread.Sleep(3000); //保证线程等待
61 }
62 Console.WriteLine("线程{0}:增加", Thread.CurrentThread.Name);
63 AddInvokeCount++; //add函数被调用的次数+1
64 }
65 }
66 }
67 /// <summary>
68 /// 这个类只是用于测试
69 /// </summary>
70 public class tester
71 {
72 public int a;
73 public int b;
74 public tester(int a, int b)
75 {
76 this.a = a;
77 this.b = b;
78 }
79 }
80 }
执行结果是:changeValue函数在线程1执行的过程中,没有发送阻塞,等待线程1执行完,而是直接执行。所以没有进行同步控制的函数可以修改被同步控制的值,如图1。

图1 没有进行同步控制的函数可以修改被同步控制的值
下面修改一下chageValue函数,其他部分不变
1 static public void changeValue() 2 { 3 lock (myList) //进行同步控制 4 { 5 tester valueToChange = myList[0];//取出第一个元素 6 valueToChange.a = 111; //这里改变List中元素的值 7 Console.WriteLine(string.Format("第一个元素被改变的值:{0}", valueToChange.a)); 8 } 9 }
执行结果,如图2。从结果中看出,如果进行同步,则changeValue函数会发生阻塞,直至他可以锁定myList。

图2 进行同步控制的函数会阻塞
作者:kissazi2
出处:http://www.cnblogs.com/kissazi2/
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

浙公网安备 33010602011771号