Java-关于重新进入的奇怪并发问题
我有2个测试用例,而第一个案例失败了,第二个可以成功。 唯一的差异代码是类cons
engry 的earm 。 为什么?
public class ReentrantSpinLockTest {
private final Incr incr = new Incr();
@Test
public void lock() throws InterruptedException {
int n = 50;
int inner_loop = 100_000;
CountDownLatch boot = new CountDownLatch(n);
CountDownLatch complete = new CountDownLatch(n);
for (int i = 0; i < n; ++i) {
new Thread(() -> {
try {
boot.await();
for (int k = 0; k < inner_loop; ++k) {
incr.incr();
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
complete.countDown();
}
}).start();
boot.countDown();
}
complete.await();
int expect = n * inner_loop;
int actual = incr.getI();
assert expect == actual : String.format("expect %d actual %d", expect, actual);
}
}
成功的递增:
public class Incr {
private final ReentrantLock lock = new ReentrantLock();
private volatile int i;
// only this diff
public void incr() {
lock.lock();
lock.lock();
i++;
lock.unlock();
lock.unlock();
}
public int getI() {
return i;
}
}
失败的递增:
public class Incr {
private final ReentrantLock lock = new ReentrantLock();
private volatile int i;
public void incr() {
int k = Math.abs(new Random().nextInt() % 5);
for (int t = 0; t < k; ++t) {
lock.lock();
}
i++;
for (int t = 0; t < k; ++t) {
lock.unlock();
}
}
public int getI() {
return i;
}
}
I have 2 test cases, while the first one is failed and the second one can successed.
The only difference code is method incr
of class Incr
.
Why?
public class ReentrantSpinLockTest {
private final Incr incr = new Incr();
@Test
public void lock() throws InterruptedException {
int n = 50;
int inner_loop = 100_000;
CountDownLatch boot = new CountDownLatch(n);
CountDownLatch complete = new CountDownLatch(n);
for (int i = 0; i < n; ++i) {
new Thread(() -> {
try {
boot.await();
for (int k = 0; k < inner_loop; ++k) {
incr.incr();
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
complete.countDown();
}
}).start();
boot.countDown();
}
complete.await();
int expect = n * inner_loop;
int actual = incr.getI();
assert expect == actual : String.format("expect %d actual %d", expect, actual);
}
}
The successful Incr:
public class Incr {
private final ReentrantLock lock = new ReentrantLock();
private volatile int i;
// only this diff
public void incr() {
lock.lock();
lock.lock();
i++;
lock.unlock();
lock.unlock();
}
public int getI() {
return i;
}
}
The failed Incr:
public class Incr {
private final ReentrantLock lock = new ReentrantLock();
private volatile int i;
public void incr() {
int k = Math.abs(new Random().nextInt() % 5);
for (int t = 0; t < k; ++t) {
lock.lock();
}
i++;
for (int t = 0; t < k; ++t) {
lock.unlock();
}
}
public int getI() {
return i;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论