zoukankan      html  css  js  c++  java
  • 线程同步傻问题:该被同步的变量没有用信号量控制,值是否会被改变

         线程同步傻问题:该被同步的变量没有用信号量控制,值是否会被改变

     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/
    本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    多线程中,上锁的理解
    sql server 2008 联机丛书
    序列化是线程安全的么
    对象化下的编程——字段
    Dic实现工厂模式
    design principle:java 回调与委派/委托机制(转)
    风筝数据结构学习笔记(2)后序遍历二叉树(非递归)
    风筝数据结构学习笔记(1)利用链式存储结构和递归构建二叉树
    吕震宇老师《设计模式系列》
    吕震宇老师《设计模式随笔系列》
  • 原文地址:https://www.cnblogs.com/kissazi2/p/2841866.html
Copyright © 2011-2022 走看看