在下面的代码中,ReentrantLock用于防止next()方法生成奇数。但next()方法生成奇数。但是,如果我将其更改为nextWith尝试它不会产生奇数。任何人都可以解释这个原因吗?
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();
}
}
答案 0 :(得分:3)
当c
和unlock
之间的其他内容增加return
时会发生什么?
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;
}
当您使用finally
时,只有在要返回的lock
的值已经在堆栈中时才会释放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();
}
}
事实上,the documentation直接建议使用try..finally
:
在大多数情况下,应使用以下习语:
Lock l = ...; l.lock(); try { // access the resource protected by this lock } finally { l.unlock(); }
这是为了避免像Exception
导致Lock
无法解锁的问题以及更严重的问题。