关于多线程,复合操作的一个小问题

大家好,我在看一篇文章的时候,内容提到

“单个方法的原子性,并不能保证 复合操作 也具有原子性”

请问这句话中的复合操作是什么意思,能举个例子说明吗?

谢谢大家

阅读 2.8k
1 个回答

参考这篇文章,我来翻译一下:

这是一个方法,它具有原子性:

    public int getVector() {
        int index = vector.size() - 1;
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return vector.get(index);
    }

这也是一个方法,它也具有原子性:

    public void deleteVector() {
        int index = vector.size() - 1;
        vector.remove(index);
    }

所谓原子性,就是方法里的语句会顺次执行,不会被打断。

但是你把它俩复合起来,它就不再是原子的了:

    public static void main(String[] args) {
        VectorTest vectorTest = new VectorTest();
        new Thread(new Runnable() {
            public void run() {
                vectorTest.getVector();
            }
        }).start();
        new Thread(new Runnable() {
            public void run() {
                vectorTest.deleteVector();
            }
        }).start();
    }

在这里开了两个线程,一个执行第一个方法,另一个执行第二个方法,第一个方法一上来先获取了向量的尺寸,然后就开始休眠了,趁第一个方法不注意,第二个方法进来删除了向量里最后一个元素,等第一个方法醒过来,再想找最后一个元素找不着了,就抛出错误了,所以复合操作不具有原子性,中间被插入打断了。

解决的方法就是加个锁:

    public int getVector(){
        synchronized (vector) {
            int index = vector.size() - 1;
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return vector.get(index);
        }
    }

synchronized就是同步的意思,同步的意思是说这一步迈不完,下一步不能开始,所以这样就保证了整个操作依然是原子级的,不存在被插入的可能。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题