使用ReentrantLock的Java中的竞争条件
在下面的代码中,ReentrantLock用于防止next()方法生成奇数。但是next()方法生成奇数。但如果我把它改成nextWithTry,它不会生成奇数。有人能解释一下原因吗使用ReentrantLock的Java中的竞争条件,java,concurrency,locking,Java,Concurrency,Locking,在下面的代码中,ReentrantLock用于防止next()方法生成奇数。但是next()方法生成奇数。但如果我把它改成nextWithTry,它不会生成奇数。有人能解释一下原因吗 class Generator{ Lock l = new ReentrantLock(); volatile int c = 0; public int next(){ l.lock(); c++; c++; l.unlock();
class Generator{
Lock l = new ReentrantLock();
volatile int c = 0;
public int next(){
l.lock();
c++; c++;
l.unlock();
return c;
}
public int nextWithTry(){//This method works fine...
try{
l.lock();
c++; c++;
return c;
}finally{
l.unlock();
}
}
}
class W implements Runnable{
private Generator r;
public W(Generator r){
this.r = r;
}
@Override
public void run() {
int x;
while(true){
if(((x = r.next()) % 2) != 0){
System.out.println(x + " odd number Found");
break;
}
}
}
}
public class Testing {
public static void main(String[] args) {
Generator r = new Generator();
W w1 = new W(r);
new Thread(w1).start();
new Thread(w1).start();
}
}
如果在
unlock
和return
之间增加了c
,会发生什么情况
public int next(){
//lock, exclusive access
l.lock();
//increment, all good
c++; c++;
//unlock, another thread can access
l.unlock();
//any number of other threads call `next` and can acquire the lock
//return some random value
return c;
}
当您最后使用时
,只有待返回的c
值已经在堆栈上时才会释放锁
:
public int nextWithTry() {
try {
//lock, exclusive access
l.lock();
//increment, all good
c++; c++;
//place the value of `c` to be returned on the stack (java passes by value)
return c;
} finally {
//unlock _after_ the return has been copied
l.unlock();
}
}
事实上,直接推荐使用try..finally
:
在大多数情况下,应使用以下习语:
Lock l = ...;
l.lock();
try {
// access the resource protected by this lock
} finally {
l.unlock();
}
这是为了避免类似这样的问题以及更严重的问题,即
异常
会导致锁
无法解锁。我正在使用java版本1.7.051和eclipse JUNO。我试着不使用挥发油。“同样的事情也会发生。”我相信你的答案是正确的。有一个排序问题,但它不是在jit的优化中,而是在您指出的代码本身。或者您可以在解锁之前将c
的值存储在局部变量中,然后返回该值,如果您想避免由于某种原因而尝试阻塞。@stvcisco是的,当然可以。但建议使用try…finally
以避免锁未释放的问题。@maamapun?