美文网首页
线程混淆

线程混淆

作者: 原创迷恋者 | 来源:发表于2019-10-14 15:37 被阅读0次

    考虑一个简单的名叫Counter的类。

    class Counter {
        private int c = 0;
    
        public void increment() {
            c++;
        }
    
        public void decrement() {
            c--;
        }
    
        public int value() {
            return c;
        }
    }
    

    Counter类被设计成如下:每次调用increment方法,都会使c加一,每次调用decrement方法,都会使c减一。但是,如果一个Counter对象被多个线程引用,多个线程之间的混淆会导致功能的失常。

    当两个运行于不同线程,却对同样的数据处理的操作出现时,混淆就发生了。这意味着有多个子步骤组成的操作,它们的顺序重叠了。

    看上去,对Counter对象的操作不可能会重叠,因为两个对变量c的操作都是单句的简单陈述。但是,即使是简单的语句,虚拟机也会把它翻译成几个步骤。比如,C++这句语句,会被分成三个步骤:

    1. 获取当前c的值。
    2. 将c的值加1。
    3. 将增加过的c存回到内存中。

    c--的操作亦然。

    假设线程A调用了increment方法,而几乎同时线程B调用了decrement方法。如果c的初始值是0,两个线程混淆的操作可能是这样的顺序:

    1. 线程A:获取c。
    2. 线程B:获取c。
    3. 线程A:对c进行加一操作,结果是1。
    4. 线程B:对c进行减一操作,结果是-1。
    5. 线程A:把结果存回c中,c现在的值是1。
    6. 线程B:把结果存回c中,c现在的值是-1。

    线程A的结果丢失了,被线程B覆盖写了。上面的这种混淆,只是一种可能性。在不同的情况下,也可能会变成线程B的结果丢失了,或者也可能没有错误。由于这是无法预料的,线程混淆的bug很难找到和修复。

    相关文章

      网友评论

          本文标题:线程混淆

          本文链接:https://www.haomeiwen.com/subject/szurmctx.html