线程安全数据集

本文关键字:数据集 安全 线程 | 更新日期: 2023-09-27 18:32:25

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

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

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);
    .
    .
    .
    }

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

线程安全数据集

不,这不安全。您应该在以下位置更改代码:

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应该在锁定部分。

更新行方法线程安全吗?

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