zoukankan      html  css  js  c++  java
  • 异步多线程(六)lock锁

    非线程安全

       引发线程安全的原因是,多个线程可以同时操作全局变量/共享变量/静态变量/磁盘文件/数据库的值就可能存在线程安全问题,因为多个线程操作,出现了覆盖。List集合也是非线程安全的。

    线程安全

    多线程同时运行,如果每次运行的结果和单线程运行的结果一致,那么就是线程安全的。

    Lock

    概念

       解决多线程冲突问题,Lock是语法糖,Monitor.Enter,占据一个引用,别的线程就只能等着。锁的本质就是把多线程在某些特定场合下变成单线程,来完成某些特定操作。

    在日常工作中,有些是特定需要锁的,更多的时候我们可以把数据拆分,避免多线程操作同一个数据,这样既安全又高效。例如有10000个任务,那可以进行拆分,某个线程执行1-100给任务。

    Lock锁不允许的类型

      Stringstring在内存分配上是重用的,会冲突。这么话应该这么理解,比如你定义一个变量name=张三”,再定义一个变量temeName=张三,那么在C#内存分配时会指向同一个引用。

      Null:可以运行,不能编译通过。

    详解Lock

    Lock锁的两钟方式:

    Lock(this)不推荐的锁如果只是当前内部实例使用,则不会冲突。外面如果也要用实例,就冲突了。 

            public void DoTest() {
                //递归调用 lock(this)不会死锁,原因:这里是同一个线程,这个引用就是被这个线程锁占据
                //锁的本质是让这个引用不会被其他线程所占据
            lock (this)
            {
                    Thread.Sleep(500);
                    iDotestNum++;
                    if (DateTime.Now.Day < 13&&iDotestNum<10)
                    {
                        
                        Console.WriteLine($"这是第{DateTime.Now.Day}天,第{iDotestNum}次");
                        this.DoTest();
                    }
                    else {
                        Console.WriteLine("结束啦");
                    }
                    }
            }
    
            private int iDotestNum = 0;

    外部也要使用实例:

                Test test = new Test();
                Task.Delay(1000).ContinueWith(t =>
                {
                    lock (test)//此处是锁住test实例
                    {
                        Console.WriteLine("*********Start**********");
                        Thread.Sleep(5000);
                        Console.WriteLine("*********End**********");
                    }
                });
                //会冲突,因为DoTest方法里的lock(this)就是锁住当前的实例即:test
                test.DoTest();
    
            public class Test{ 
    
            public void DoTest() {
                //递归调用 lock(this)不会死锁,原因:这里是同一个线程,这个引用就是被这个线程锁占据
                //锁的本质是让这个引用不会被其他线程所占据
            lock (this)
            {
                    Thread.Sleep(500);
                    iDotestNum++;
                    if (DateTime.Now.Day < 13&&iDotestNum<10)
                    {
                        
                        Console.WriteLine($"这是第{DateTime.Now.Day}天,第{iDotestNum}次");
                        this.DoTest();
                    }
                    else {
                        Console.WriteLine("结束啦");
                    }
                    }
            }
    
            private int iDotestNum = 0;
        }

    标准锁,微软推荐的标准锁

    private static readonly object Form_Lock = new object();

    lock(Form_Lock);

                #region 标准锁
    
                for (int i = 0; i < 1000; i++)
                {      
                       Task.Run(() =>
                       {
                           lock (Form_Lock)// 任意时刻只有一个线程能进入方法块儿
                           {
                               intAsyncNum++;
                           }
                       });
                }
                Console.WriteLine($"intAsyncNum={intAsyncNum}");
    
                #endregion
  • 相关阅读:
    dubbo入门(一)
    java中文件操作《一》
    Unity 游戏框架搭建 2019 (七) 自定义快捷键
    凉鞋:我所理解的框架 【Unity 游戏框架搭建】
    Unity 游戏框架搭建 2019 (六) MenuItem 复用
    Unity 游戏框架搭建 2019 (五) 打开所在文件夹
    Unity 游戏框架搭建 2019 (四) 导出 UnityPackage
    Unity 游戏框架搭建 2019 (三) 生成文件名到剪切板
    Unity 游戏框架搭建 2019 (二) 文本复制到剪切板
    Unity 游戏框架搭建 2019 (一) 简介与第一个示例文件名的生成
  • 原文地址:https://www.cnblogs.com/JohnTang/p/11010476.html
Copyright © 2011-2022 走看看