我有一些代码可以在具有给定token的数据库中创建一个新行,或者如果现有行已经存在,则返回该行:
public static RunSet ProvisionRun(ApplicationDbContext context, IIdentity identity, string token, CrewType crewType)
{
   var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
   var user = manager.FindById(identity.GetUserId());
   var runSet = user.RunSets.SingleOrDefault(r => r.RunName == token);
   if (runSet != null) // Run set already created, they must be uploading new files to this run; return existing run
      return runSet;
   // Create the run
   var newRun = new RunSet
   {
      Created = DateTime.Now,
      CrewType = crewType.ToString(),
      RunName = token,
      InputFiles = new List<RunFile>()
   };
   user.RunSets.Add(newRun);
   context.SaveChanges();
   return newRun;
}这很好,但是多个线程可能同时调用此代码,从而产生具有相同RunName的多个行(这会创建唯一的约束冲突)。为了避免这种情况,我可以在这段代码周围放置一个lock语句:
private static readonly Object _lock = new Object();
public static RunSet ProvisionRun(ApplicationDbContext context, IIdentity identity, string token, CrewType crewType)
{
   lock (_lock)
   {
      // Same stuff here
      return newRun;
   }
}这就解决了这个问题。但是,没有两个用户会传入同一个token,所以我真正想做的是阻止同一个用户调用该方法,但允许两个不同的用户同时调用该方法。我应该能够锁定用户的身份:
lock (identity.Name) // This is a string
{
   // Same stuff here
   return newRun;
}然而,这是行不通的。我已经在调试器中完成了它,实际上它只是直接遍历lock,尽管identity.Name在两个线程中都是相同的:

我有点倾向于相信lock关键字可以实现精确的引用相等,这是有意义的。然而,在MSDN上的锁文件中,它清楚地指出了相反的情况:

我假设框架有一个哈希锁,并将检查对象相等。它也可能是文档误导性的,因为它使用的是一个字符串常量,而这个常量将被嵌入。
不管怎样,很明显,我对锁的理解有一些差距。有人要填这些吗?谢谢!
发布于 2015-11-04 18:06:39
我构建了这个简单的类,用于像您这样的情况:
public class NamedLock : IDisposable
{
    public NamedLock(string name)
    {
        if (name == null)
        {
            throw new ArgumentNullException();
        }
        mutex = new Mutex(false, name);
        mutex.WaitOne();
    }
    public void Dispose()
    {
        if (mutex != null)
        {
            mutex.ReleaseMutex();
            mutex = null;
        }
    }
    private Mutex mutex;
}用法如下:
using(new NamedLock(identity.Name))
{
    // do some stuff
}但是要小心“命名互斥”:
因为它们是系统范围的,所以可以使用命名互斥来协调跨进程边界的资源使用。
关于您的问题,我还猜测您的字符串有不同的引用,锁语句处理的是引用相等而不是值相等,这对我来说是有意义的。
https://stackoverflow.com/questions/33528651
复制相似问题