使用 ReentrantLock Java 中的竞争条件
Race Condition in Java With ReentrantLock
在下面的代码中,ReentrantLock 用于防止通过 next() 方法生成奇数。但是 next() 方法生成奇数。但是如果我将它更改为 nextWithTry 它不会生成奇数。谁能解释一下这是什么原因?
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;
}
当你使用 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
:
In most cases, the following idiom should be used:
Lock l = ...;
l.lock();
try {
// access the resource protected by this lock
} finally {
l.unlock();
}
这是为了避免像这样的问题以及更严重的问题,其中 Exception
导致 Lock
无法解锁。
在下面的代码中,ReentrantLock 用于防止通过 next() 方法生成奇数。但是 next() 方法生成奇数。但是如果我将它更改为 nextWithTry 它不会生成奇数。谁能解释一下这是什么原因?
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;
}
当你使用 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
:
In most cases, the following idiom should be used:
Lock l = ...; l.lock(); try { // access the resource protected by this lock } finally { l.unlock(); }
这是为了避免像这样的问题以及更严重的问题,其中 Exception
导致 Lock
无法解锁。