在类中使用状态和可变对象的多线程计算

本文关键字:对象 多线程 计算 状态 | 更新日期: 2023-09-27 18:35:52

我正在学习多线程,但是我不知道如何在我的研究场景中实现线程安全。

这是一个伪代码,所以我有一个类,可以执行一些计算并共享一些公共数据(公式列表),并且有一个公共属性 ID 来进一步阅读:

class Problem{
  public int Id {get; set;}
  public IList<Calc> Formulas {get; private set;}
  public Problem(int id){
    Id = id;
    Formulas = new List<Formulas>();
  }
  public void SolveProblem(){
    Calc newCalc = DoSomeCalculations();
    Formulas.Add(newCalc);
  }
  private Calc DoSomeCalculations(){
    var originalFormulas = Formulas.Where(x => x.Number > 2);
    return new Calc(originalFormulas);
  }
}

我做了一个类来运行许多线程的大量计算:

class ProblemsRunner{
  public void Run(List<Problem> problemsToSolve){
    var thread1 = new Thread(RunProblem(problemsToSolve.Take(10)));
    var thread2 = new Thread(RunProblem(problemsToSolve.Skip(10).Take(10)));
    var thread3 = new Thread(RunProblem(problemsToSolve.Skip(20).Take(10)));
    thread1.Start();
    thread2.Start();
    thread3.Start();
  }
  private void RunProblem(IEnumerable<Problem> problems){
    foreach(var problem in problems){
      problem.SolveProblem();
    }
  }
}

我不知道我的代码中我关注什么:

  • 类问题共享的数据(公式列表和属性 ID)和我只需要锁定其访问权限吗?

  • 我是否需要在 ProblemRunner 中担心,并将整个对象锁定在 ProblemRunner.RunProblem() foreach 循环中?

因为经过计算,我需要知道每个对象的 Id 和公式,而我无法弄清楚如何使用多线程来做到这一点。

你不需要纠正所有代码(但请随意),我要求一些方向来解决这个问题,并实现线程安全......在类相关内具有状态和可变对象

在类中使用状态和可变对象的多线程计算

您的代码似乎没有任何您担心的问题。每个问题都有自己的Formulas,因此当您在解决问题后添加新公式时,您不会访问可能从另一个线程访问的任何内容。

不过,我怀疑这不是您的意图。你可能想要一个Formulas;在这种情况下,您当然需要一个线程安全列表。

您应该使用某种线程安全的阻塞队列来管理要解决的问题,并让每个线程在完成当前线程时从队列中取出另一个。您当前向每个线程发送 10 个线程的方法的问题在于,如果前 10 个线程的解决速度比后 10 个线程快,则第一个线程将闲置。如果在线程空闲时动态分配,则所有线程将一直处于繁忙状态(最后除外)。