为了账号安全,请及时绑定邮箱和手机立即绑定

实例化新实例是否使所有代码线程安全?

实例化新实例是否使所有代码线程安全?

C#
小唯快跑啊 2021-09-19 15:40:37
编辑代码以使其成为线程安全的帖子评论请参阅最后更新的问题。你能帮我理解这段代码是线程安全的还是如何使它成为线程安全的?设置我的系统有一个非常简单的类,称为 WorkItem。public class WorkItem{    public int Id {get;set;}    public string Name {get;set;}    public DateTime DateCreated {get;set;}    public IList<object> CalculatedValues {get;set;}    }有一个接口 ICalculator,它有一个方法,它接受一个工作项,执行计算并返回 true。public interface ICalculator{    bool Calculate(WorkItem WorkItem);}假设我们有两个 ICalculator 的实现。public class BasicCalculator: ICalculator{    public bool Calculate(WorkItem WorkItem)    {        //calculate some value on the WorkItem and populate CalculatedValues property         return true;    }}另一个计算器:public class AnotherCalculator: ICalculator{    public bool Calculate(WorkItem WorkItem)    {        //calculate some value on the WorkItem and populate CalculatedValues property        //some complex calculation on work item        if (somevalue==0) return false;        return true;    }最后,在我的客户端类中,我注入了与运行相关的 ICalculators[]。然后我实例化 ExecuteCalculators() 方法。现在我有大量的工作项,我想对它们执行计算,所以我创建了一个任务列表,其中每个任务负责实例化 CalculatorHandler 实例,然后获取一个工作项并通过执行 WaitAll() 来执行计算所有的任务这是系统的简化版本。实际系统有一系列计算器,Calculators 和 CalculatorHandler 是通过 IoC 等注入的。我的问题是 - 帮助我理解以下几点:每个任务都会创建一个 CalculatorHandler 的新实例。这是否意味着 CalculatorHandler 中发生的任何事情都是线程安全的,因为它没有任何公共属性并且只是在计算器上循环?计算器在所有任务之间共享,因为它们是 Client 类的成员变量,但它们被传递到为每个任务实例化的 CalculatorHandler。这是否意味着当所有任务运行时,由于创建了 CalculatorHandler 的新实例,因此 Calculators 是自动线程安全的,我们不会遇到任何线程问题,例如死锁等?你能建议我如何使代码线程安全吗?是否最好将Func<'ICalculators>'[]传递给 Client 类,然后在每个任务中,我们可以执行 Func<'ICalculator'>() 然后将这些实例传递给 ICalculator 那里?Func<'ICalculator'> 将返回 ICalculator 的实例。计算器是作为私有方法变量传入的,因此 CalulatorHandler 的其他实例不能运行相同的计算器实例,这是真的吗?还是因为计算器是引用类型,我们必然会遇到多线程问题?
查看完整描述

2 回答

?
尚方宝剑之说

TA贡献1788条经验 获得超4个赞

  1. 不,它不是线程安全的。如果在任何计算中存在任何共享状态,则可能存在线程问题。避免线程问题的唯一方法是确保您没有更新任何共享状态。这意味着只读对象和/或使用“纯”函数

  2. 您已经使用了“共享”这个词——这意味着由于共享状态而不是线程安全的。除非你的意思是“分布式”而不是“共享”。

  3. 独占使用只读对象。

  4. 它们是引用类型,因此它们可以在不同的线程之间共享——因此不是线程安全的——除非它们是只读的。

下面是一个只读对象的例子:

public sealed class WorkItem : IEquatable<WorkItem>

{

    private readonly int _id;

    private readonly string _name;

    private readonly DateTime _dateCreated;


    public int Id { get { return _id; } }

    public string Name { get { return _name; } }

    public DateTime DateCreated { get { return _dateCreated; } }


    public WorkItem(int id, string name, DateTime dateCreated)

    {

        _id = id;

        _name = name;

        _dateCreated = dateCreated;

    }


    public override bool Equals(object obj)

    {

        if (obj is WorkItem)

            return Equals((WorkItem)obj);

        return false;

    }


    public bool Equals(WorkItem obj)

    {

        if (obj == null) return false;

        if (!EqualityComparer<int>.Default.Equals(_id, obj._id)) return false;

        if (!EqualityComparer<string>.Default.Equals(_name, obj._name)) return false;

        if (!EqualityComparer<DateTime>.Default.Equals(_dateCreated, obj._dateCreated)) return false;

        return true;

    }


    public override int GetHashCode()

    {

        int hash = 0;

        hash ^= EqualityComparer<int>.Default.GetHashCode(_id);

        hash ^= EqualityComparer<string>.Default.GetHashCode(_name);

        hash ^= EqualityComparer<DateTime>.Default.GetHashCode(_dateCreated);

        return hash;

    }


    public override string ToString()

    {

        return String.Format("{{ Id = {0}, Name = {1}, DateCreated = {2} }}", _id, _name, _dateCreated);

    }


    public static bool operator ==(WorkItem left, WorkItem right)

    {

        if (object.ReferenceEquals(left, null))

        {

            return object.ReferenceEquals(right, null);

        }


        return left.Equals(right);

    }


    public static bool operator !=(WorkItem left, WorkItem right)

    {

        return !(left == right);

    }

}

一旦创建就无法修改,因此线程安全不再是问题。


现在,如果我可以假设每一个ICalculator都是在没有状态的情况下实现的,因此是一个纯函数,那么计算就是线程安全的。但是,您的问题中没有任何内容让我知道我可以做出这个假设。因此,任何人都无法告诉您您的代码是线程安全的。


因此,考虑到只读WorkItem和纯ICalculator函数,您的其余代码看起来会非常好。


查看完整回答
反对 回复 2021-09-19
  • 2 回答
  • 0 关注
  • 152 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信