比较和交换不正确的值

时间:2013-10-05 22:50:43

标签: java concurrency locking atomic

我有以下代码用于锁定具有特定用户ID的对象

 public boolean acquireLock(Long id) {
   if (lock.compareAndSet(0L, id)) { 
    return true ; 
  }
  return false ; 
}

我通过以下方式获得它:

      while(!parent.acquireLock(id)){
        System.out.println(lock.get());
        if (count++>1000000) {
          System.out.println(id + " Trying to acquire " + lock.get());
          DebugHandler.createException("Error, deadlock");

        }
      }

将其发布为:

public boolean releaseLock(Long id) { 

  if (lock.compareAndSet(id, 0)) {
    System.out.println("Releasing Lock for " + id);
    return true ; 
  }
  else { 
    DebugHandler.createException("Lock not owned by current view. Thief");
    return false ;
  }

}

并将锁定对象声明为:

 private volatile AtomicLong lo = new AtomicLong(0); 

除了我得到以下奇怪的行为和死锁,其结论是:

Id 45试图获得0

Ak,锁的值系统地为0,但是比较和交换测试失败,认为它不是0.(在退出循环后,重新初始化了用于测试死锁的计数器)

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

我可以看到您的代码存在问题。如果你得到一个id为零的线程,你的锁定方案就会崩溃,两个线程最终可能同时持有这个锁。

修复:对您的acquireLockreleaseLock方法添加防御性检查,以测试id是否为非。

关于代码如何进入明显陷入僵局的状态:

  • 这真的是一个真正的僵局。例如,如果某个线程在已经拥有该id的锁定时尝试获取给定id的锁定,则可能会发生这种情况。 (您实施的锁是不可重入的。)

  • 您的代码可能无法释放给定id的锁定;例如因为抛出了异常并且跳过了对releaseLock的正常调用。