Java-关于重新进入的奇怪并发问题

发布于 2025-01-29 20:05:03 字数 2045 浏览 1 评论 0原文

我有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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文