Java并发编程-AtomicInteger与synchronized实现Count的区别

首先,线程不安全的写法如下

public class NotThreadCount {
    static int val = 0;
    public static void main(String[] args) throws InterruptedException {
        NotSafeThreadCount notSafeThreadCount=new NotSafeThreadCount();
        Thread thread1=new Thread(notSafeThreadCount);
        Thread thread2=new Thread(notSafeThreadCount);
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println(val);
    }
    static class NotSafeThreadCount implements Runnable {
        @Override
        public void run() {
            for (int i=0;i<10000;i++){
                val++;
            }
        }
    }
}

AtomicInteger写法

发现这个交替进行导致的线程不安全,最终执行结果并非是20000
试着用AtomicInteger进行递增


public class AtomicThreadCount {
    public static void main(String[] args) throws InterruptedException {
        Runnable runnable=new AtomicThread();
        Thread thread1=new Thread(runnable);
        Thread thread2=new Thread(runnable);
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println(count.get());
    }
    static AtomicInteger count=new AtomicInteger();
    static class AtomicThread implements Runnable{
        @Override
        public void run() {
            for (int i = 0; i <10000 ; i++) {
                count.incrementAndGet();
            }
        }
    }
}

这样就变成了线程安全了。

synchronized写法

我们再试试synchronized进行加锁

public class NotThreadCount {
    static int val = 0;
    public static void main(String[] args) throws InterruptedException {
        NotSafeThreadCount notSafeThreadCount=new NotSafeThreadCount();
        Thread thread1=new Thread(notSafeThreadCount);
        Thread thread2=new Thread(notSafeThreadCount);
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println(val);
    }
    static class NotSafeThreadCount implements Runnable {
        @Override
        public void run() {
        synchronized(this){
            for (int i=0;i<10000;i++){
                val++;
            }
           }
        }
    }
}

那么有个疑问就出现了,同样是实现原子性,这两者有什么区别?

在作用范围上,synchronized修饰的范围更广泛,synchronized可以加在类上,也可以用在方法上
但是在粒度上,AtomicInteger要比synchronized更细,比如在修饰一行代码的时候,使用synchronization则需要考虑是否更笨拙,所以,在简单的需要代码段上使用AtomicInteger实现原子性更加轻便。
最大的区别则是synchronized是悲观锁,而AtomicInteger主要利用的是乐观锁
所以说依据悲观锁的特性,虽然开销很大,但是是一种固定的开销,一劳永逸。
乐观锁虽然短期开销比较小但是随着时间的推移,开销是呈线性增长的,所以在并发量并不是特别大的情况下,可以优先考虑乐观锁也就是AtomicInteger实现,在并发量特别大,竞争特别激烈的情况下,可以优先考虑synchronized,而且在不断地优化下,synchronized不断改善,已经成为一种轻量级锁,所以,synchronized也是一种不错的选择。

你可能感兴趣的:(Java基础)