zoukankan      html  css  js  c++  java
  • C# 多线程总结

    1.Thread

    1.1 Thread生命周期

    1.2 Thread本地存储

    本地存储槽

    Local Store Slot(本地存储槽):存储的信息只对该线程有用,这叫做线程本地化存储

                //1.给所有线程分配一个(未命名)数据槽。 存放数据
                var slot = Thread.AllocateDataSlot();
                Thread.SetData(slot, "hello world");
    
                //2.给所有线程分配一个(aaa)数据槽。 存放数据
                var slotaaa = Thread.AllocateNamedDataSlot("aaa");
                Thread.SetData(slotaaa, "hello world aaa");
    
                var slotObj = Thread.GetData(slot);
                var slotObjaaa = Thread.GetData(slotaaa);
    
                Console.WriteLine(slotObj);
                Console.WriteLine(slotObjaaa);
    
    
                //消除进程与槽位
                Thread.FreeNamedDataSlot("aaa");
    

    ThreadStatic

    性能提升:

          [ThreadStatic]
            static string username = string.Empty;
    
            static void Main(string[] args)
            {
                username = "hello world!!!";
    
                var t = new Thread(() =>
                {
                    Console.WriteLine("当前工作线程:{0}", username);
                });
    
                t.Start();
    
                Console.WriteLine("主线程:{0}", username);
    
                Console.Read();
            }
    
    

    ThreadLocal

                ThreadLocal<string> local = new ThreadLocal<string>();
    
                local.Value = "hello world!!!";
    
                var t = new Thread(() =>
                {
                    Console.WriteLine("当前工作线程:{0}", local.Value);
                });
    
                t.Start();
    
                Console.WriteLine("主线程:{0}", local.Value);
    

    1.3 认识MemoryBarrier

    2个线程同时操作一个变量时,这个变量可能加载到Cpu Cache中。这时,就使用到MemoryBarrier

    例子:因为Release中做了一些代码和缓存的优化。。。 比如说将一些数据从memory中读取到cpu高速缓存中。

    static void Main(string[] args)
            {
                var isStop = false;
    
                var t = new Thread(() =>
                {
                    var isSuccess = false;
    
                    while (!isStop)
                    {
    		    Thread.MemoryBarrier(); //及时从cpu cache中更新到 memor
                        isSuccess = !isSuccess;
                    }
                });
    
                t.Start();
    
                Thread.Sleep(1000);
                isStop = true;
                t.Join();
    
                Console.WriteLine("主线程执行结束!");
                Console.ReadLine();
            }
    

    在此方法之前的内存写入都要及时从cpu cache中更新到 memory。
    在此方法之后的内存读取都要从memory中读取,而不是cpu cache。

    类似的功能还有:

     var isStop = 0;
    
                var t = new Thread(() =>
                {
                    var isSuccess = false;
    
                    while (isStop == 0)
                    {
                        Thread.VolatileRead(ref isStop);
                        isSuccess = !isSuccess;
                    }
                });
    

    1.4ThreadPool 线程池

    使用线程池的线程,要调用静态方法 ThreadPool.QueueUserWorkItem ,以指定线程要调用的方法。该静态方法有两种:

    public static bool QueueUserWorkItem(WaitCallback callBack);  
    
    public static bool QueueUserWorkItem(WaitCallback callBack, object state); 
    

    这两个方法用于向线程池队列添加一个工作项(work item)以及一个可选的状态数据。

    工作项是指一个由 callback 参数标识的委托对象,被委托对象包装的回调方法由线程池来执行。

    传入的回调方法匹配 System.Threading.WaitCallback 委托类型

            private void button2_Click(object sender, EventArgs e)
            {
                Console.WriteLine("主线程ID={0}", Thread.CurrentThread.ManagedThreadId);
    
                ThreadPool.QueueUserWorkItem(CallbackWorkItem);
    
                ThreadPool.QueueUserWorkItem(CallbackWorkItem, "work");
    
                Thread.Sleep(3000);
    
                Console.WriteLine("主线程退出");
    			
    	    //线程池线程ID = 5
                //主线程ID = 1
                //线程池开始执行
                //线程池开始执行
                //线程池线程ID = 6
                //线程池线程ID = 3 传入的参数为 work
                //主线程退出
            }
    
            private static void CallbackWorkItem(object state)
            {
                Console.WriteLine("线程池开始执行");
    
                if (state != null)
                {
                    Console.WriteLine("线程池线程ID = {0} 传入的参数为 {1}", Thread.CurrentThread.ManagedThreadId, state.ToString());
    
                }
    
                else
                {
                    Console.WriteLine("线程池线程ID ={0}", Thread.CurrentThread.ManagedThreadId);
                }
            }
    

    工作者线程与I/O线程

    CLR线程池分为工作者线程(workerThreads)与I/O线程 (completionPortThreads) 两种,

    工作者线程是主要用作管理CLR内部对象的运作,I/O(Input/Output) 线程顾名思义是用于与外部系统交换信息.

    I/O 线程是.NET专为访问外部资源所设置的一种线程,因为访问外部资源常常要受到外界因素的影响,为了防止让主线程受影响而长期处于阻塞状态,.NET为多个I/O操作都建立起了异步方法,例如:FileStream、TCP/IP、WebRequest、WebService等等,而且每个异步方法的使用方式都非常类似,都是以BeginXXX为开始,以EndXXX结束

  • 相关阅读:
    软件工程个人作业01
    学习进度条
    课堂练习:增加信息
    JavaWeb学习-1
    构建之法阅读笔记02
    java笔记04: String的理解与运用
    java:凯撒密码
    java笔记3(动手动脑)
    Java学习笔记--异常
    Advice详解
  • 原文地址:https://www.cnblogs.com/tangge/p/13472312.html
Copyright © 2011-2022 走看看