zoukankan      html  css  js  c++  java
  • C#中多线程中变量研究

    今天在知乎上看到一个问题【为什么在同一进程中创建不同线程,但线程各自的变量无法在线程间互相访问?】。在多线程中,每个线程都是独立运行的,不同的线程有可能是同一段代码,但不会是同一作用域,所以不会共享。而共享内存,并没有作用域之分,同一进程内,不管什么线程都可以通过同一虚拟内存地址来访问,不同进程也可以通过ipc等方式共享内存数据。全局变量:任何线程都可以访问;局部变量(栈变量):任何线程执行到该函数时均可访问,函数外不可访问;线程变量:每个线程只能访问自己的那个拷贝,其他线程不可见。今天就用C#来实现同一段代码的不同线程,全局变量、局部变量、线程变量。

    了解进程与线程

    什么是多任务,简单来说就是操作系统同时可以运行多个任务。例如:一遍听歌,一遍写文档等。多核CPU可以执行多任务,但是单核CPU也可以执行多任务,CPU是顺序执行的,操作系统让任务轮流执行,例如:听歌执行一次,停顿0.01s,写文档执行一次,停顿0.01s等等。由于CPU的执行速度很快,我们感觉就像所有的任务都是同时执行。对操作系统来说,一个任务就是一个进程,一个进程至少有一个线程。进程是资源分配的最小单位,线程是CPU调度的最小单位。

    普通的程序写法

    private static List<int> data = Enumerable.Range(1, 1000).ToList();
    
    public static void SimpleTest()
    {
        for (int i = 0; i < 10; i++)
        {
            List<int> tempData = new List<int>();
            foreach (var d in data)
            {
                tempData.Add(d);
            }
            Console.WriteLine($"i:{i},合计:{data.Sum()},是否相等:{data.Sum() == tempData.Sum()}");
        }
    
        Console.WriteLine("单线程运行结束");
    }

    多线程写法

    private static List<int> data = Enumerable.Range(1, 1000).ToList();
    
    public static async Task MoreTaskTestAsync()
    {
        List<Task> tasks = new List<Task>();
        for (int i = 0; i < 10; i++)
        {
            var tempi = i;
            var t = Task.Run(() =>
            {
                List<int> tempData = new List<int>();
                foreach (var d in data)
                {
                    tempData.Add(d);
                }
                Console.WriteLine($"i:{tempi},合计:{data.Sum()},是否相等:{data.Sum() == tempData.Sum()}");
            });
            tasks.Add(t);
        }
    
        await Task.WhenAll(tasks); //或者Task.WaitAll(tasks.ToArray());
        Console.WriteLine("多线程运行结束");
    }

    不同的线程同一段代码,但不会是同一作用域,所以tempData数据没有互相影响。

    全局变量:data,多个线程都可以访问,list只读的时候是线性安全
    局部变量:i就是局部变量,访问的线程可以访问,去掉【var tempi = i;】,运行结果打印出来,值都是一样的,增加的都是每个线程都访问单独的tempi变量

    i:10,合计:500500,是否相等:True
    i:10,合计:500500,是否相等:True
    i:10,合计:500500,是否相等:True
    i:10,合计:500500,是否相等:True
    i:10,合计:500500,是否相等:True
    i:10,合计:500500,是否相等:True
    i:10,合计:500500,是否相等:True
    i:10,合计:500500,是否相等:True
    i:10,合计:500500,是否相等:True
    i:10,合计:500500,是否相等:True

    线程变量:tempData,每个线程只访问自己的,互不影响,运行结果

    i:3,合计:500500,是否相等:True
    i:6,合计:500500,是否相等:True
    i:0,合计:500500,是否相等:True
    i:1,合计:500500,是否相等:True
    i:4,合计:500500,是否相等:True
    i:2,合计:500500,是否相等:True
    i:7,合计:500500,是否相等:True
    i:5,合计:500500,是否相等:True
    i:8,合计:500500,是否相等:True
    i:9,合计:500500,是否相等:True

    写多线程的时候需要注意,变量的作用域,否则程序运行出来的结果将不会是想要的结果,注意,注意变量作用域。

    其他的多线程文章

    1. C#中await/async闲说

    2. .NET中并行开发优化

    3. C# Task.Run 和 Task.Factory.StartNew 区别

    4. C#中多线程的并行处理

  • 相关阅读:
    JavaScript 将十进制数转换成格式类似于 0x000100 或 #000100 的十六进制数
    Java 从资源文件(.properties)中读取数据
    更改MySQL 5.7的数据库的存储位置
    PADS Layout VX.2.3 将PCB中的元器件封装保存到库
    怀疑安装MySQL之后,导致OrCAD Capture、Allegro就打不开
    Allegro PCB 转 PADS Layout 之后的修修补补
    Java 使用UDP传输一个小文本文件
    IntelliJ IDEA Commons IO环境搭建
    RestFul风格API(Swagger)--从零开始Swagger
    Spring容器的简单实现(IOC原理)
  • 原文地址:https://www.cnblogs.com/zhao123/p/11084692.html
Copyright © 2011-2022 走看看