C# 线程和线程安全-如何管理线程内外的数据

C# 线程和线程安全-如何管理线程内外的数据,c#,multithreading,C#,Multithreading,我正在努力自学c#的线程技术,我已经阅读了大量的教程、问题和示例。我已经成功地(*这似乎可行)实现了线程到更大的应用程序中,但对我来说,这是一些非常灰色的领域 我试着把一个小的控制台应用程序放在一起,作为讨论的重点,并尝试回答提出的问题。我不是一个有经验的程序员,所以如果我在这里犯了一些致命的错误,我真诚地道歉。请随意指出它们,以提高我的编程技能。希望我在这里提出的问题能帮助我和其他试图理解线程的人 第一个问题是——如果我打电话 ThreadStart()中的randomNums.Genrate

我正在努力自学c#的线程技术,我已经阅读了大量的教程、问题和示例。我已经成功地(*这似乎可行)实现了线程到更大的应用程序中,但对我来说,这是一些非常灰色的领域

我试着把一个小的控制台应用程序放在一起,作为讨论的重点,并尝试回答提出的问题。我不是一个有经验的程序员,所以如果我在这里犯了一些致命的错误,我真诚地道歉。请随意指出它们,以提高我的编程技能。希望我在这里提出的问题能帮助我和其他试图理解线程的人

  • 第一个问题是——如果我打电话 ThreadStart()中的randomNums.GenrateRandomNumbers(),会这样吗 被认为是不安全的。我的结论是 正在从其他线程调用PrintRandomCNumbers(),并且 意味着物体将处于非常不确定的状态

  • 如果我想打randomNums.GenrateRandomNumbers,会是什么 线程安全的调用方式?我将如何以及在何处实施 锁,我会使用写,多读锁吗

  • 当我运行这个应用程序时,每个线程都正确地输出 randomNums的内容,是否存在场景(多处理器或 核心),如果给定此实现,则信息不会 显示以输出,但对象引用的副本仍在 范围即,随机数变为空

  • 如果没有硬件场景,我将如何操作它 示例生成这样的场景。也就是说,Threadmanger Randomnums对象引用,但它只是指向 未初始化的对象,但尝试初始化该对象。(我有一个 在我的大型应用程序中也存在类似的问题。)

  • 将数据输入和输出的最佳设计实践是什么 线

  • 在设计线程开始时,管理 对象内部或外部线程的起点和顶部


  • 使用系统;
    使用System.Collections.Generic;
    使用System.Linq;
    使用系统文本;
    //采用系统线程技术;
    使用系统线程;
    名称空间线程示例
    {
    班级计划
    {
    静态void Main(字符串[]参数)
    {
    MyApplication app=新的MyApplication();
    app.Start();
    }
    公共类MyApplication
    {
    私有随机数;
    公共应用程序()
    {
    }
    公开作废开始()
    {
    randomNums=新的随机数();
    randomNums.GenrateRandomNumbers();
    randomNums.PrintRandomcNumbers();
    ThreadManager newThreadMan=newthreadmanager(随机数);
    Console.ReadLine();
    }
    }
    公共类线程管理器
    {
    私有随机数;
    私有线程[]新线程;
    私有整数线程计数;
    公共线程管理器(随机数newRandomNums)
    {
    线程数=3;
    随机数=新随机数;
    newThreads=新线程[threadCount];
    对于(int i=0;i
  • 正如所写的那样,调用随机数实际上已经足够安全了,这是一种糟糕的做法,因为随机数会根据当时执行的线程而变化,这里需要记住的是,如果在每个线程中存储变化的数字,比如一个是6,另一个线程的数字是12,然后两个线程都会有一个随机数列表,其中有12个数字,而有6个的线程只会更改列表中的前6个元素,而不会调整列表本身的大小

  • 关于如何安全地从内部线程更改数据,最简单的解释是不要。实际上,我会找到一种不同的方法来做这件事。例如,如果您发现自己需要在每个线程中显示不同的随机数,请生成不同的列表并将其传递给线程

  • 由于您没有像编写此程序时那样实例化新对象,因此该程序将正常工作,数据可能与您期望的不完全相同,但不会出现数据不在其中的情况

  • 实际上,强制失败很简单,每次调用GeneratorDomainNumbers函数时,都要实例化一个新列表。这会导致矮子
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    // Using System Threading for theads;
    using System.Threading;
    
    namespace ThreadingExamples
    {
        class Program
        {
    
            static void Main(string[] args)
            {
                MyApplication app = new MyApplication();
                app.Start();
            }
    
    
            public class MyApplication
            {
                private RandomNumbers randomNums;
    
    
                public MyApplication()
                {
    
                }
    
                public void Start()
                {
                    randomNums = new RandomNumbers();
                    randomNums.GenrateRandomNumbers();
                    randomNums.PrintRandomcNumbers();
    
                    ThreadManager newThreadMan = new ThreadManager(randomNums);
    
                    Console.ReadLine();
                }
    
            }
    
            public class ThreadManager
            {
                private RandomNumbers randomNums;
                private Thread[] newThreads;
                private int threadCount;
    
                public ThreadManager(RandomNumbers newRandomNums)
                {
                    threadCount = 3;
                    randomNums = newRandomNums;
                    newThreads = new Thread[threadCount];
                    for (int i = 0; i < threadCount; i++)
                    {
                        newThreads[i] = new Thread(ThreadStart);
                        newThreads[i].Start();
                    }
                }
                public void ThreadStart()
                {
                    randomNums.PrintRandomcNumbers();
                }
    
            }
    
            public class RandomNumbers
            {
                private Random rnd = new Random();
                private int numberToStore;
                private int[] randomNumbers;
    
                public RandomNumbers()
                {
                    numberToStore = 12;
                    randomNumbers = new int[numberToStore];
                }
    
                public void GenrateRandomNumbers()
                {
                    for (int i = 0; i < numberToStore; i++)
                    {
                        randomNumbers[i] = rnd.Next(1,13);
                    }
                }
                public void PrintRandomcNumbers()
                {
                    StringBuilder outputString = new StringBuilder();
                    for (int i = 0; i < numberToStore; i++)
                    {
                        outputString = new StringBuilder("The Random Numbers in position ");
                        outputString.Append(i.ToString());
                        outputString.Append("is the number: ");
                        outputString.Append(randomNumbers[i].ToString());
    
                        Console.WriteLine(outputString);
                    }
                }
            }
        }
    }
    
    public void GenrateRandomNumbers()
        {
            randomNumbers=new List<int>();
            for (int i = 0; i < numberToStore; i++)
            {
                randomNumbers[i] = rnd.Next(1,13);
            }
        }