正在跳过锁定

时间:2013-02-09 07:20:44

标签: c# asp.net multithreading thread-safety locking

我有以下代码可以完成一些数据库工作:

[WebMethod]
public void FastBulkAdd(int addmax){
Users[] uploaders = db.Users.Take(addmax).ToArray();

Parallel.ForEach(uploaders, item =>
{
    Account account;
    lock (this)
    {
        account = item.Account;
    }
}

每个用户都有1个帐户,通过外键在DB中的另一个表中引用(我确定每个用户只有1个帐户)。我必须锁定那段代码,因为多线程数据库连接会产生错误。当我将此设置addmax设置为1(允许1个线程执行)时,它运行正常,但如果addmax大于1且执行了多个线程,则帐户将始终为null,这将生成稍后会有例外。这几乎就像锁被忽略了一样。

更新:我不相信帐户永远是空的,所以我做了以下事情:

int tries = 0;
while (account == null && tries < 100)
{
    lock (this)
    {
        account = item.Account;
    }
    tries++;
}

它有效。不是一个非常简洁的解决方案。我想知道问题的原因,以便将来可以避免这种设计危险。

3 个答案:

答案 0 :(得分:2)

item.Account进行数据库查找,对吗?您可以立即用所有上传者帐户的批量选择替换它吗?这样你只需要选择一个数据库进行选择,然后一个命中数据库就可以稍后进行批量更新,而且你不关心同步数据库访问(无论如何,每次额外命中需要花费大量时间)

答案 1 :(得分:0)

而不是锁定this创建private static object并锁定它;你可以参考this thread

此外,您需要验证item.Account不为null。另一个问题是,即使您锁定了Account,您似乎也在以后的代码中使用它。这似乎不对,即使您正在锁定,然后它可能会在您将其保存到数据库的部分中更改,因为它未锁定。请参阅以下示例;

lock (this)
{
    account = item.Account;
}
DoSomeDatabaseOperation(account); // the account may change here when another thread is also operating.

您也可以调试并行操作;请参阅this msdn page

答案 2 :(得分:0)

您可以使用[MethodImpl(MethodImplOptions.Synchronized)] 例如

  [MethodImpl(MethodImplOptions.Synchronized)]
    [WebMethod]
    public void FastBulkAdd(int addmax)
    {
    }

有关详细信息,请参阅以下链接。  http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.methodimploptions.aspx