C# 如果我';在更新数据行时,是锁定整个数据表还是仅锁定数据行?

C# 如果我';在更新数据行时,是锁定整个数据表还是仅锁定数据行?,c#,.net,datatable,thread-safety,datarow,C#,.net,Datatable,Thread Safety,Datarow,假设我正在从多个线程访问一个DataTable。如果我想访问某一行,我怀疑我需要锁定该操作(我可能对此有误解,但至少我知道这样我是安全的): 但是,如果我想更新该行,我应该再次锁定该表(或者更确切地说,该表的行.SyncRoot对象),还是可以简单地锁定该行?您不需要为读取而锁定,只需为写入/更新而锁定。锁定尽可能小的数量,以确保数据一致性。。。通常只更新一行。如果要更新表之间的父/子关系,则需要锁定每个表中的每一行。datatable仅适用于多线程读取操作: 在阅读有关datatable的

假设我正在从多个线程访问一个
DataTable
。如果我想访问某一行,我怀疑我需要锁定该操作(我可能对此有误解,但至少我知道这样我是安全的):


但是,如果我想更新该行,我应该再次锁定该表(或者更确切地说,该表的
行.SyncRoot
对象),还是可以简单地锁定该行?

您不需要为读取而锁定,只需为写入/更新而锁定。锁定尽可能小的数量,以确保数据一致性。。。通常只更新一行。如果要更新表之间的父/子关系,则需要锁定每个表中的每一行。

datatable仅适用于多线程读取操作:


在阅读有关datatable的信息时,关于锁定表并允许您安全地更新行中数据的能力存在冲突。根据第二个链接,可以锁定表并更新行。由于这是来自MS MVP,我想说您可能可以锁定该表,并且一切正常。

实际上,仅在DataTable或DataRow上的一个位置执行
锁定
,实际上并没有做任何事情。使用
监视器
锁(这就是
块)时要记住的一个重要方面是,锁定对象不会对其产生任何影响;这是一些人提倡使用专用锁定对象而不是锁定资源本身的原因之一,因为这会迫使您意识到,无论何时处理资源,都必须执行锁定(以及对同一对象执行锁定)

也就是说,最好锁定整个
DataTable
,因为数据存储本身就在那里(
DataRow
对象内部只包含
DataTable
中的一个偏移量,以确定在哪里检索数据)。因此,即使同步对单个行的访问,同时更新两个不同的行也会导致以非同步方式更新相同的数据存储机制

在这里,将内部类型视为“黑匣子”和只锁定所需内容(在本例中,这将导致您得出只锁定行的错误结论)与试图深入了解类型的内部工作方式以及依赖可能更改的实现细节之间存在冲突


结果是,现在,您应该锁定整个
数据表
,以避免以非同步方式更新内部数据存储系统

链接上说:“这种类型对于多线程读取操作是安全的。您必须同步任何写入操作”这难道不意味着锁是多线程访问的正确方法吗?我很困惑;您提供的第一个链接似乎表明您只需要锁定写入(尽管它没有说明要锁定什么)。第二种方法似乎表明锁定表是正确的方法。两人似乎都不同意您的说法,即不能锁定表并期望读取一致。我遗漏了什么吗?我的第一句话不正确。我发现了相互矛盾的信息。您不需要锁定表来读取数据,因为这样就可以了。您需要锁定表来写入数据。Kevin()提供的链接似乎确实表明锁定表是必要的。MSFT代表说:“假设更新一行不会影响表中的任何其他内容,这是危险的,因为您依赖的是可能在以后很容易被破坏的潜在实现细节。”您对这是否属实有任何见解吗?非常有洞察力的回答,我可以理解为什么你觉得有必要指出
机制是如何工作的。。。我确实意识到锁定对对象没有任何作用;我想我可以用一种更好的方式来表达我的问题,那就是“我需要同步每行或每表的更新操作吗?”在任何情况下,现在我很清楚,我必须同步整个表中的任何行的更新——无论是通过锁定表还是专用的“表锁”(在本例中,我认为
Rows.SyncRoot
对象实际上很好地实现了这一目的)。
// this is a strongly-typed table
OrdersRow row = null;
lock (orderTable.Rows.SyncRoot) {
    row = orderTable.FindByOrderId(myOrderId);
}