非线程安全与线程同步技术

非线程安全是指多线程操作用一个对象可能出现问题。
线程安全就是多线程访问时,采用加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到这个线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。
线程不安全就是不提供数据访问保护,有可能多个线程先后更改数据造成所得到的数据是脏数据。

看下面这个例子:

        static int num = 0;
        static void Main(string[] args)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            for(int i = 0; i < 5; i++)
            {
                Thread thread = new Thread(Run);
                thread.Start();
            }
            num++;
            Console.WriteLine("num is:" + num);
            Console.WriteLine("Main thread ID is:"+Thread.CurrentThread.ManagedThreadId);
            sw.Stop();
            Console.ReadKey();
        }
        static void Run()
        {

                num++;
                Console.WriteLine("num的值是:" + num);
                Console.WriteLine("child thread's id is " + Thread.CurrentThread.ManagedThreadId);
        }

结果:
在这里插入图片描述多次运行发现num 的值有时并不是连续递增的,输出也是没有顺序的,每次输出的值都不相同,这是因为异步线程同时访问一个成员时造成,这样的多线程对我们来说是不可控的。
这就是典型非线程安全问题,解决这个问题要用线程同步。线程同步方法很多,
下面说第一种。

  1. 使用Thread.Join()方法,这个方法是阻塞调用线程,直到某个线程终止时为止。我们把它加到代码中看看效果。还是上面那个例子,我们在主方法中加入Join方法。
        static int num = 0;
        static void Main(string[] args)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            for(int i = 0; i < 5; i++)
            {
                Thread thread = new Thread(Run);
                thread.Join();
                thread.Start();
            }
            num++;
            Console.WriteLine("num is:" + num);
            Console.WriteLine("Main thread ID is:"+Thread.CurrentThread.ManagedThreadId);
            sw.Stop();
            Console.ReadKey();
        }
        static void Run()
        {

                num++;
                Console.WriteLine("num的值是:" + num);
                Console.WriteLine("child thread's id is " + Thread.CurrentThread.ManagedThreadId);
        }

再看运行结果
在这里插入图片描述num现在是连续递增的且输出有序了。main方法其实就是一个主线程,我们在主线程中调用另外一个线程,此时的主线程被称为调用线程,被调用的线程,被称为被调用线程。在主线程(主方法)中写入thread.join()方法,运行时主线程被阻塞,要等到被调用线程执行完后,才继续执行。

  1. 使用lock
    lock语法
         private static object  ojb = new object();
        lock(obj)
        {
                 //锁定运行的代码段
        } 

常用的做法是创建一个object对象,并且永不复制,应lock一个不影响其他操作的的私有对象。
示例:

        private static object locker = new object(); //创建一个object对象
        static int num = 0;
        static void Main(string[] args)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            for(int i = 0; i < 5; i++)
            {
                Thread thread = new Thread(Run);
                thread.Start();
                //thread.Join();//用Join()方法实现线程同步
            }
            num++;
            Console.WriteLine("num is:" + num);
            Console.WriteLine("Main thread ID is:"+Thread.CurrentThread.ManagedThreadId);
            sw.Stop();
            Console.ReadKey();
        }
        static void Run()
        {
            lock(locker)
            {
                num++;
                Console.WriteLine("num的值是:" + num);
                Console.WriteLine("child thread's id is " + Thread.CurrentThread.ManagedThreadId);
           }
            
        } 

在这里插入图片描述num也是有序递增的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值