繁体   English   中英

C#:数据线程安全问题

[英]C#: datatable thread safety questions

我有一个名为DataStorage的单例obj,它在我的应用程序中存储了常见数据; 其中一个是名为myTable的数据表,它将被多个线程读取和写入。 我有一个私有对象用作DataStorage中的锁,即

private object lockObj = new object();

我已经围绕访问myTable包装了锁:

private DataTable myTable;
public DataTable MyTable
{
    get
    { lock(lockObj) { return myTable; } }
    set
    { lock(lockObj) { myTable = value; } }
}

另一个对象即MyObj将获取此数据表,对其执行选择,然后从Select中检索检索到的DataRow []中的某个值。 我已经读过Select不是线程安全的,所以我写了这样的代码:

// lock on MyTable
DataTable dt = DataStorage.Instance.MyTable;

lock (MyObjLockObj)  // lock object for MyObj class
{
    // do a select, then modify value in the returned row
    DataRow[] foundRows = dt.Select("some expression");
    foundRows[0]["some col"] = 123456;
}

问题:1。总的来说,这段代码是否是线程安全的?

  1. 当我在MyObj中修改检索到的DataRow时,MyTable setter是否确保其线程安全? 因为setter用于设置DataTable,而不是DataRow。

  2. 我应该将访问DataStorage.Instance.MyTable的代码移动到与Select相同的锁定块中吗?

提前致谢。

你的代码不是线程安全的,因为:

对属性的锁定只能确保一个线程不能同时使用get / set属性,但在有权访问后,它们可以同时更改它。

线程可以使用MyTable属性获取数据表的instacne。 之后,另一个thred可以使用该属性来获取相同的实例。 然后,在他们都可以访问myTable之后,他们都可以直接写入,而无需同步。

所以将存取器移动到一个锁也无济于事。

最好提供更改数据的方法,并在这些方法中进行同步,而不是直接公开数据表。

getter和setter中的那些锁完全没用。 'myTable = value'操作已经是原子操作,无需将其包装在锁中。 当然,这个锁与修改行无关。 然而,该锁(MyObjLockObj)确保只有一个线程将访问您的数据表,如果您的应用程序使用相同的MyObjLockObj。 如果您不经常使用该数据表,那么这不会有问题,但是如果您的应用程序只是搞乱该数据表,那么您将遇到性能问题。

总而言之,在多线程应用程序中使用单个数据表是一个糟糕的决定。 如果从DB读取该数据表的数据,则应该为每个线程读取一个数据表,修改其行并将更改提交回DB。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM