Java 比较并交换不正确的值
我有以下代码用于锁定具有特定用户ID的对象Java 比较并交换不正确的值,java,concurrency,locking,atomic,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+
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。(用于测试死锁的计数器在我退出循环后重新初始化)
有什么想法吗?我发现你的代码有问题。如果某个线程的
id
为零,那么锁定方案将崩溃,两个线程可能会同时持有锁
修正:在acquireLock
和releaseLock
方法中添加防御检查,以测试id
是否为非零
至于您的代码如何进入明显的死锁状态:
- 这可能真的是一个真正的僵局。例如,如果线程试图获取给定
的锁,而它已经持有该id
的锁,则可能会发生这种情况。(实现的锁是不可重入的。)id
- 您的代码可能无法释放给定
的锁;e、 g.因为引发了异常,并且跳过了对id
的正常调用releaseLock
this.getWorldID()
,但您的日志使用的是this.id
。请修复此问题并重新测试,然后让我们知道结果是什么。它真的总是0吗?有时可以预期它为0。这并不意味着死锁,只是自旋锁由另一条线程持有AtomicLong
是原子的,但它没有阻塞。您是否记得在成功时将count
设置为0?是的,它始终为0,至少在1000000次迭代中。我确实重置了计数。您正在调用parent.acquireLock()
,但正在打印lock.get()
。那些是同一把锁吗parent.lock
看起来更像您正在寻找的锁。ID在1开始分配时不是0。调试输出显示,非0 id线程试图获取值为0的锁,但CaS测试仍然失败。1)无论如何,您应该包括0
的防御检查。2) CaS测试失败的原因是锁已经被其他东西持有。我给了你两种可能的解释。可能还有其他人。