线程安全数据集
本文关键字:数据集 安全 线程 | 更新日期: 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
应该在锁定部分。
更新行方法线程安全吗?
不,不是。每次输入方法时,都会在新对象上创建锁。您锁定的对象在所有线程中必须相同 - 否则锁定将永远不会被视为"已获取",因为每个线程都会愉快地在之后丢弃的对象上创建一个新锁。实现此目的的一种方法是将锁定的对象也设置为静态。