使用C#示例锁定以使类线程安全,还是该类线程安全?
我正在尝试研究锁定以创建一个threadsafe类,并有几个问题。鉴于以下类别:使用C#示例锁定以使类线程安全,还是该类线程安全?,c#,locking,thread-safety,C#,Locking,Thread Safety,我正在尝试研究锁定以创建一个threadsafe类,并有几个问题。鉴于以下类别: public class StringMe { protected ArrayList _stringArrayList = new ArrayList(); static readonly object _locker = new object(); public void AddString(string stringToAdd)
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) 是只修改需要锁定的数据的方法,还是读写操作都需要锁定以使其线程安全
非常感谢您抽出时间
1) 我是否成功地使AddString和ToString线程安全
是,如果将\u stringArrayList
更改为私有
2) 在我创建的ToString方法中,是否需要将其锁定以使其线程安全
对
3) 是只修改需要锁定的数据的方法,还是读写操作都需要锁定以使其线程安全
读和写。三者都是(即读/写到最后一个)
但还有更多:
将锁定对象设置为静态,而保护的数据是每个实例字段。这意味着StringMe
的所有实例都受到保护,尽管它们具有不同的数据(即\u stringArrayList
的实例)。对于您给出的示例,您可以从\u locker
中删除static
修饰符。更准确地说,您通常为一组数据定义一个“锁”,或者为您想要保留的更好的不变量定义一个“锁”。因此,锁的生存期(和作用域)通常应该与数据的生存期(和作用域)相等
此外,为了更好地衡量,您对所保护的数据的可见性不应高于对锁的可见性。在您的示例中,派生实现可以在不获取锁的情况下更改
\u stringArrayList
(因为它受到保护),从而破坏不变量。我将使它们都私有
,如果必须的话,只通过(正确锁定)方法向派生类公开\u stringArrayList
。不,您没有使这些调用线程安全-因为\u stringArrayList
字段受到保护。在调用AddString
和ToString
时,子类可以用它做任何事情
例如(其他答案声称您的代码是线程安全的。)
然后:
更喜欢私有字段-这样可以更容易地对代码进行推理
此外:
- 现在更喜欢
而不是List
ArrayList
- 由于某种原因,您正在使用静态变量锁定。。。因此,即使您有多个
实例,一次只能有一个线程在StringMe
中AddString
- 使用
比typeof(string)
Type.GetType(“System.string”)
全部,假设可能有一些操作。如果一切都只是读取,那么就不需要任何锁——但是,否则,即使只有一个写入线程,您的读取线程也可以从数据结构中读取两位数据,而这两位数据是在其间修改过的。(还需要考虑内存模型。)读卡器也必须锁定-如果只锁定写入器,读卡器下的数据可能会更改,这可能会导致异常。查看
\u锁柜
不必(不应该)是静态的。回答得很好!非常感谢你。这对我来说非常好+1,如果可以的话,我会更多!
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");