• 你没用过的.net4.0


    项目升级到.net 4.0很久了,但很多语法和知识点,还停留在以前的版本的有木有?

    今天,我们就一块来看一下在.net 4.0的环境下我们如何编程的。

    先从锁开始。需要你有一点点操作系统和多线程的基础哦。

    再拉回过去,在处理并发的时候,平日大家都是如何实现一个锁的呢?

    • Lock

    早在1.0时代,就有了Lock关键字,我们想实现一个自增长的场景:让多线程有序的访问静态类JingTai的num字段,不发生并发。

    public  static class JingTai 
    
    { 
    
    public static int num = 0; 
    
    } 
    
    class Program 
    
    { 
    
    static void Main(string[] args) 
    
    { 
    
    //我们想实现一个场景:
    
    //让多线程有序的访问静态类JingTai的num字段,不发生并发
    
    int d = 23; 
    
    Thread[] thread = new Thread[d]; 
    
    for (int i = 0; i < d; i++) 
    
    { 
    
    thread[i] = new Thread(new ThreadStart(GaiBianJingTai)); 
    
    thread[i].Start(); 
    
    } 
    
     
    
    Console.ReadLine();//这一句只是为了查看结果使用
    
    } 
    
    static void GaiBianJingTai() 
    
    { 
    
    Random r = new Random(); 
    
    int n = r.Next(111, 1111); 
    
    Thread.Sleep(n); 
    
     
    
    lock (typeof(JingTai))//请注意:如果没有lock(注释此行),每次的结果是不确定的,而且可能有重复的
    
    { 
    
    Console.WriteLine(JingTai.num++); 
    
    } 
    
    } 
    
    } 
    

    Lock太简单了,我们就不赘述了。继续。。。

    • Monitor

    Monitor也可以实现同样的功能,为共享资源加锁;他在.Net2.0的时代就已经出现了。

    View Code
        public static class JingTai
        {
    
            public static int num = 0;
             
        }
    
        class Program
        {
    
            static void Main(string[] args)
            {
    
                //我们想实现一个场景:
    
                //让多线程有序的访问静态类JingTai的num字段,不发生并发
    
                int d = 23;
    
                Thread[] thread = new Thread[d];
    
                for (int i = 0; i < d; i++)
                {
    
                    thread[i] = new Thread(new ThreadStart(GaiBianJingTai));
    
                    thread[i].Start();
    
                }
    
    
    
                Console.ReadLine();//这一句只是为了查看结果使用
    
            }
    
            static void GaiBianJingTai()
            {
    
                Random r = new Random();
    
                int n = r.Next(111, 1111);
    
                Thread.Sleep(n);
    
                Monitor.Enter(typeof(JingTai));
    
                Console.WriteLine(JingTai.num++);
    
                Monitor.Exit(typeof(JingTai));
    
            }
    
        }

    我们来分析一下使用Monitor,他的致命缺陷在于性能:

    线程使用Monitor访问共享的资源时候,如果他不能拿到锁,线程状态会有运行转换为阻塞,只以为着将会进行一个线程上下文的切换。如果每个线程对共享资源的访问时间很短,比如我们的只是num的值加1,那么使用Monitor必然带来频繁的线程上下文的切换,明显影响到程序运行的性能。

    好了,镜头拉回现在.net4.0平台,微软才推出了新的自旋锁SpinLock。

    • SpinLock

    当一个线程需要访问资源的时候,他调用SpinLock.Enter方法申请独占锁,如果不能获得锁(此时可能运行于另一个CPU核上的线程正在占有这个资源),当前线程就会空转若干个时间片,然后等下次时间片轮询到他的时候,他再尝试申请这个独占锁,在这个过程中该线程一直保持着运行时的状态哦,不会出现上下文的切换。

    View Code
     public class JingTai
        {
            public static int num = 0;
            public int day = 0;
        }
        class Program
        {
            static void Main(string[] args)
            {
                //我们想实现一个场景:
                //让多线程有序的访问静态类JingTai的num字段,不发生并发
                int d = 23;
                Thread[] thread = new Thread[d];
                for (int i = 0; i < d; i++)
                {
                    thread[i] = new Thread(new ThreadStart(GaiBianJingTai));
                    thread[i].Start();
                }
    
                Console.ReadLine();//这一句只是为了查看结果使用
            }
            /*
             * 以下是微软给出的注意事项
             SpinLock 仅当您确定这样做可以改进应用程序的性能之后才能使用。
             * 另外,务必请注意 SpinLock 是一个值类型(出于性能原因)。
             * 因此,您必须非常小心,不要意外复制了 SpinLock 实例,因为两个实例(原件和副本)之间完全独立,这可能会导致应用程序出现错误行为。
             * 如果必须传递 SpinLock 实例,则应该通过引用而不是通过值传递。
             * 不要将 SpinLock 实例存储在只读字段中。
    
             */
            private static SpinLock spin = new SpinLock();//创建一个自旋锁,注意:他的类型是struct 哦
            static void GaiBianJingTai()
            {
                bool lockTaken = false;
                 
                try
                {
                    spin.Enter(ref lockTaken);
                    Console.WriteLine(JingTai.num++);
                }
                finally
                {
                    if (lockTaken)
                        spin.Exit();
    
                }
    
            }
        }

    对于单核CPU,使用SpinLock的效率和Monitor相比差别不大,,但是在多喝CPU环境下,在合适的场景下使用SpinLock取代Monitor,效率大大的提升。

    另外,SpinLock 的所有成员都是线程安全的,可从多个线程同时使用。

    下一次我想说说.net4.0才有的多核环境下的并行开发。

    出处:http://www.cnblogs.com/angben 欢迎转载,也请保留这段声明。谢谢!

    好了,今天就说这些,嗯,就这些了。

  • 相关阅读:
    计算机图形学的学习资源
    Matlab绘图基础
    Matlab绘图函数一览
    Matlab编程基础
    Python实现对文件夹内文本文件递归查找
    C++预处理详解
    C++的学习资源
    OGRE启动过程详解(OGRE HelloWorld程序原理解析)
    Bullet核心类介绍(Bullet 2.82 HelloWorld程序及其详解,附程序代码)
    windows下Bullet 2.82编译安装(Bullet Physics开发环境配置)
  • 原文地址:https://www.cnblogs.com/angben/p/2806858.html
Copyright © 2020-2023  润新知