Java并发编程(二)原子性

1,606 阅读3分钟

banner窄.png

铿然架构  |  作者  /  铿然一叶 这是铿然架构的第 32 篇原创文章

相关阅读:
Java并发编程(一)知识地图
Java并发编程(三)可见性
Java并发编程(四)有序性
Java并发编程(五)创建线程方式概览
Java并发编程入门(六)synchronized用法
Java并发编程入门(七)轻松理解wait和notify以及使用场景
Java并发编程入门(八)线程生命周期
Java并发编程入门(九)死锁和死锁定位
Java并发编程入门(十)锁优化
Java并发编程入门(十一)限流场景和Spring限流器实现
Java并发编程入门(十二)生产者和消费者模式-代码模板
Java并发编程入门(十三)读写锁和缓存模板
Java并发编程入门(十四)CountDownLatch应用场景
Java并发编程入门(十五)CyclicBarrier应用场景
Java并发编程入门(十六)秒懂线程池差别
Java并发编程入门(十七)一图掌握线程常用类和接口
Java并发编程入门(十八)再论线程安全
Java并发编程入门(十九)异步任务调度工具CompleteFeature
Java并发编程入门(二十)常见加锁场景和加锁工具


一、一个小测验

并发情况下,下面两个类是否线程安全?

public class Counter {
    private int count;
    
    public void increase() {
        count = count + 1;
    }
    
    public int getCount() {
      return count;
    }
}

public class Basket {
    //Vector是线程安全的集合
    Vector<Fruit> v = new Vector<Fruit>();

    public void put(Fruit fruit) {
        v.add(fruit);
    }

    public Fruit tackOut() throws Exception {
        if (v.size() > 0) {
            return v.remove(0);
        } else {
            throw new Exception("There is no fruit in basket.");
        }
    }
}

答案:以上两个类在并发情况下均不能保证线程安全。

二、线程安全和原子性

线程安全:当多个线程访问某个类时,这类始终都能表现出正确的行为,那么这个类是线程安全的。

原子性:一个或者多个操作在CPU执行的过程中不被中断的特性称为原子性。

而以上两个类不能保证操作原子性导致不能表现正确的行为,因此都不是线程安全的。

1.在类Counter中,以下代码实际执行了三个指令:

count = count + 1;

在多线程并发情况下由于线程切换会导致计算结果不正确。

注:图片参考Java并发编程实战

2.在类中的如下代码不是原子的,可能会导致抛出空指针异常和预期不符:

if (v.size() > 0) {
    return v.remove(0);
}

三、修正

原子性可以通过加锁来解决,修正如下:

public class Counter {

    private int count;
    
    public synchronized void increase() {
        count = count + 1;
    }
    
    /** 原子操作可不加同步关键字 */
    public int getCount() {
      return count;
    }
}

public class Basket {

    Vector<Fruit> v = new Vector<Fruit>();

    /** 原子操作可不加同步关键字 */
    public void put(Fruit fruit) {
        v.add(fruit);
    }

    /** 加上synchronized关键字 */
    public synchronized Fruit tackOut() throws Exception {
        if (v.size() > 0) {
            return v.remove(0);
        } else {
            throw new Exception("There is no fruit in basket.");
        }
    }
}

end.


<--阅过留痕,左边点赞 !