zoukankan      html  css  js  c++  java
  • Intern Day85

    线程安全

    多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时会进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。

    线程同步

    是指多线程程序中,为了保证后者线程,只有等待前者线程完成之后才能继续执行。就好比买票,前面的人没买到票之前,后面的人必须等待。所谓同步:是指在某一时刻只有一个线程可以访问变量。如果不能确保对变量的访问是同步的,就会产生错误。c#为同步访问变量提供了一个非常简单的方式,即用c#语言的关键字Lock,它可以把一段代码定义为互斥段,互斥段在一个时刻内只允许一个线程进入执行,而其他线程必须等待。

    作用和使用场景

    作用:锁可以阻止其它线程执行锁块(lock(o){})中的代码,当锁定时,其它线程必须等待锁中的线程执行完成并释放锁。但是这可能会给程序带来性能影响。

    使用场景:锁不太适合I/O场景,例如文件I/O,繁杂的计算或者操作比较持久的过程,会给程序带来很大的性能损失。

    lock语法

    Lock(expression) // expression:你希望跟踪的对象
    {
        statement_block // 互斥段的代码,这段代码在一个时刻内只可能被一个线程执行
    }
    

    lock加锁的对象和原因

    对象:

    1. 加锁主要用于锁住引用型的公共变量,eg:class

    2. lock锁定的是一个引用类型,而值类型的变量,如int、struct是不能用lock的

    原因:见:https://www.cnblogs.com/tianciliangen/p/4910394.html

    lock加锁的注意事项

    1. lock只是保证资源不被占用,不会保证执行顺序。 有可能一个线程在循环里连续获得了lock(锁)。所以下面的代码每次运行的时候结果都是不一样的。

    2. 如果一个类的实例是public的,最好不要lock(this)。因为使用你的类的人也许不知道你用了lock,如果他new了一个实例,并且对这个实例上锁,就很容易造成死锁。(即:如果type是public类型的,不要lock(typeof(type))。)

    3. 不要去锁一个string,因为程序中任何 跟锁定的string的字符串是一样的 都会被锁定。

    具体代码

    using System;
    using System.Diagnostics;
    using System.Threading;
    using System.Threading.Tasks;
    
    class Program
    {
        // private object locker = new object(); 
        private static readonly object Locker = new object(); // 这个比上面的语句好
        // 设成只读的原因:这时因为如果在lock代码段中改变obj的值,其它线程就畅通无阻了
        
        static int num = 1;
    
        static void Main(string[] args)
        {
            Program program = new Program();
            
            Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();
            
            for (int i = 0; i < 4; i++)
            {
                Thread thread = new Thread(program.Run);
                thread.Start(); 
            }
            
            // for (int i = 0; i < 4; i++) wrong
            // {
            //     var t= Task.Run(() =>  // Task.Run(async () =>
            //     {
            //         program.Run();
            //     });
            //     t.Start();
            //     Task.WaitAll(t);
            // }
    
            num++; 
            Console.WriteLine("num = " + num);
            Console.WriteLine("主线程ID = " + Thread.CurrentThread.ManagedThreadId.ToString()); 
            
            stopWatch.Stop();
            
            Console.WriteLine("执行时间 = " + stopWatch.ElapsedMilliseconds + "ms"); 
            Console.ReadKey(); 
        }
        
        public  void Run()
        {
            // 加锁主要用于锁住引用型的公共变量,比如class、string
            // 而值类型的变量,如int、struct是不能用锁的 
            
            // lock里面尽量少放东西,否则影响效率
            lock (Locker)  // 这里的就是上面定义的公共变量locker
            {
                num++;
                Console.WriteLine("num = " + num);
                Console.WriteLine("子线程ID = " + Thread.CurrentThread.ManagedThreadId.ToString());
            } 
        }
    }
    
  • 相关阅读:
    算法图解——求Int整型数二进制中1的个数
    图解算法——句子逆序
    图解算法——反转字符串
    图解算法——整数倒置
    《图解算法》之狄克斯特拉算法
    图解算法——合并两个有序链表
    图解算法——括号匹配
    图解算法——两数之和
    #热烈庆祝我党成立100周年#
    jQuery全选反选
  • 原文地址:https://www.cnblogs.com/OFSHK/p/14765061.html
Copyright © 2011-2022 走看看