2

我想对 DataTable/DataSet 线程安全进行更新操作。有 ~20 个线程,每个线程使用 DataTable 的Rows.Find(pk)方法更新 ~40 行全局 DataTable。每个线程都将更新不同的 DataTable 行。

我正在为 DataSet 使用以下包装类。这种方法是线程安全的吗?

public sealed class MyDataSet{

    public static DataSet ds = new DataSet();

    public static UpdateRow(key,data)
    {
        object _lock = new object();
        DataRow dr = ds.Tables[0].Rows.Find(key);
        lock(_lock){          
            dr.AcceptChanges();
            dr.BeginEdit();
            dr["col"] = data;
            dr.EndEdit();
        }
    }
}

此方法从for循环中调用。

for(int x=0; x<40; x++;){
    if(someCondition)
    .
    .
    .
    MyDataSet.UpdateRow(key,data);
    .
    .
    .
    }

一切都在多线程环境中完成。UpdateRow 方法线程安全吗?

4

2 回答 2

6

不,这不安全。你应该改变你的代码:

public sealed class MyDataSet{

    public static DataSet ds = new DataSet();

    private static object _lock = new object();

    public static UpdateRow(key,data)
    {
        lock(_lock){
            DataRow dr = ds.Tables[0].Rows.Find(key);
            dr.AcceptChanges();
            dr.BeginEdit();
            dr["col"] = data;
            dr.EndEdit();
        }
    }
}

您的_lock对象应该是程序中的静态对象,以使其成为良好的锁。你Find应该在锁定的部分。

于 2012-04-26T16:29:51.237 回答
1

UpdateRow 方法线程安全吗?

不,这不对。每次输入该方法时,您都会在新对象上创建一个锁。您锁定的对象在所有线程中必须相同 - 否则锁定将永远不会被视为“被占用”,因为每个线程都会愉快地在它之后丢弃的对象上创建一个新锁。实现此目的的一种方法是将您锁定的对象也设为静态。

于 2012-04-26T16:29:45.070 回答