锁定以使类具有C#示例的线程安全性,或者该类是线程安全的

本文关键字:线程 安全性 安全 或者 锁定 | 更新日期: 2023-09-27 18:20:42

我正试图研究锁定以创建线程安全类,并有几个问题。给定以下类别:

    public class StringMe 
    {
        protected ArrayList  _stringArrayList = new ArrayList();
        static readonly object _locker = new object();
        public void AddString(string stringToAdd)
        {
            lock (_locker) _stringArrayList.Add(stringToAdd);
        }
        public override string ToString()
        {
            lock (_locker)
            {
return string.Join(",",string[])_stringArrayList.ToArray(Type.GetType("System.String")));
            }
        }
    }

1) 我是否成功地使AddString和ToString线程安全?

2) 在我创建的ToString方法中,是否需要将其锁定以确保线程安全?

3) 是否只有修改数据的方法需要锁定,或者执行读取和写入操作的方法都需要锁定以确保线程安全?

非常感谢您抽出时间!

锁定以使类具有C#示例的线程安全性,或者该类是线程安全的

不,您还没有使这些调用成为线程安全的,因为_stringArrayList字段是受保护的。当调用AddStringToString时,子类可以用它做任何他们喜欢的事情。

例如(其他答案声称您的代码线程安全的。)

public class BadStringMe : StringMe
{
    public void FurtleWithList()
    {
        while (true)
        {
            _stringArrayList.Add("Eek!");
            _stringArrayList.Clear();
        }
    }
}

然后:

BadStringMe bad = new BadStringMe();
new Thread(bad.FurtleWithList).Start();
bad.AddString("This isn't thread-safe");

更喜欢私有字段-这样可以更容易地对代码进行推理。

另外:

  • 现在更喜欢List<T>而不是ArrayList
  • 由于某种原因,您正在使用静态变量锁定。。。因此,即使您有几个StringMe实例,一次也只能有一个线程在AddString
  • 使用typeof(string)比使用Type.GetType("System.String")干净得多

3) 是否只有修改数据的方法需要锁定,或者执行读取和写入操作的方法都需要锁定以确保线程安全?

所有,假设可能存在一些操作。如果所有都只是读取,则不需要任何锁,但否则,即使只有一个写入线程,您的读取线程也可以从数据结构中读取两位数据,这两位数据在其间进行了修改。(还需要考虑内存模型。)

1) 我是否成功地使AddString和ToString线程安全?

是的,如果您将_stringArrayList更改为专用

2) 在我创建的ToString方法中,是否需要将其锁定以确保线程安全?

3) 是否只有修改数据的方法需要锁定,或者执行读取和写入操作的方法都需要锁定以确保线程安全?

读写。

对所有三个都是(即读/写到最后一个)。

但还有更多:

您将锁定对象设为static,而保护的数据是每个实例的字段。这意味着StringMe的所有实例都受到相互保护,尽管它们具有不同的数据(即_stringArrayList的实例)。对于您给出的示例,可以从_locker中删除static修饰符。更准确地说,您通常为一组数据定义一个"锁",或者更好的是,您想要保留的不变量。通常情况下,锁的生存期(和作用域)应该等于数据的生存期。

此外,为了更好地衡量,您对所保护的数据的可见性不应高于对锁的可见性。在您的示例中,派生实现可以在不获取锁的情况下更改_stringArrayList(因为它是受保护的),从而破坏不变量。我会使它们同时为private,并且如果必须的话,只通过(正确锁定)方法向派生类公开_stringArrayList