Java 杂谈java多线程

Java 多线程(九):Atomic 包

2018-06-09  本文已影响43人  聪明的奇瑞

无锁意味着方法未加锁,直观表现为线程之间存在着交叉执行

非原子操作例如 number++; number = number + 1; 这些操作实际上分为好几步执行

Atomic 包介绍

Atomic 的作用

为了更好的让大家明白 Atomic 的作用,下面通过两个案例来进行分析

AtomicInteger 实现多线程安全加法

Code 1(非线程安全)

public class Code1 {
    public static void main(String[] args) {

        Test test = new Test(0);

        for (int j = 0; j < 100; j++)
            new Thread(test).start();

        System.out.println(test.number);
    }

    public static class Test implements Runnable {

        public int number;

        public Test(int number) {
            this.number = number;
        }

        @Override
        public void run() {
            number = number + 1;
            number = number + 2;
            number = number + 3;
            number = number + 4;
        }
        
    }
}

Code 2 (使用 volatile,仍非线程安全)

public class Code2 {
    public static void main(String[] args) {

        Test test = new Test();

        for (int j = 0; j < 100; j++)
            new Thread(test).start();

        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("number------------"+test.number);
    }

    public static class Test implements Runnable {

        volatile public int number;

        public Test() {
            this.number = 0;
        }

        @Override
        public void run() {
            number = number + 1;
            System.out.println("ThreadId-" + Thread.currentThread().getId() + " : " + number);
            number = number + 2;
            System.out.println("ThreadId-" + Thread.currentThread().getId() + " : " + number);
            number = number + 3;
            System.out.println("ThreadId-" + Thread.currentThread().getId() + " : " + number);
            number = number + 4;
            System.out.println("ThreadId-" + Thread.currentThread().getId() + " : " + number);
        }
    }
}
.....
ThreadId-108 : 974
ThreadId-108 : 980
ThreadId-108 : 983
ThreadId-109 : 984
ThreadId-107 : 978
ThreadId-109 : 990
ThreadId-109 : 993
ThreadId-108 : 988
ThreadId-109 : 997
number------------997

Code 3 (使用 AtomicInteger,线程安全)

public class Code3 {
    public static void main(String[] args) {

        Test test = new Test(0);

        for (int j = 0; j < 100; j++)
            new Thread(test).start();
    }

    public static class Test implements Runnable {

        public AtomicInteger number;

        public Test(int number) {
            this.number = new AtomicInteger(number);
        }

        @Override
        public void run() {
            number.addAndGet(1);
            System.out.println("ThreadId-" + Thread.currentThread().getId() + " : " + number);
            number.addAndGet(2);
            System.out.println("ThreadId-" + Thread.currentThread().getId() + " : " + number);
            number.addAndGet(3);
            System.out.println("ThreadId-" + Thread.currentThread().getId() + " : " + number);
            number.addAndGet(4);
            System.out.println("ThreadId-" + Thread.currentThread().getId() + " : " + number);
        }
    }
}
......
ThreadId-108 : 977
ThreadId-108 : 983
ThreadId-108 : 986
ThreadId-109 : 987
ThreadId-108 : 991
ThreadId-109 : 993
ThreadId-109 : 996
ThreadId-109 : 1000

AtomicBoolean 解决并发多次初始化问题

Code 1(非并发安全)

public class Code1 {
    public static void main(String[] args) {
        Test test = new Test(true);
        for (int j = 0; j < 100; j++)
            new Thread(test).start();
    }

    public static class Test implements Runnable {

        public boolean flag;

        public Test(boolean flag) {
            this.flag = flag;
        }

        public void init() {
            if (flag) {
                System.out.println("初始化中1");
                System.out.println("初始化中2");
                System.out.println("初始化完毕");
                flag = false;
            }
        }

        @Override
        public void run() {
            init();
        }

    }
}
初始化中1
初始化中2
初始化完毕
初始化中1
初始化中2
初始化完毕

Code 2(使用 AtomicBoolean)

public class Code2 {
    public static void main(String[] args) {
        Test test = new Test(true);
        for (int j = 0; j < 100; j++)
            new Thread(test).start();
    }

    public static class Test implements Runnable {

        AtomicBoolean atomicBoolean;

        public Test(boolean flag) {
            this.atomicBoolean = new AtomicBoolean(flag);
        }

        public void init() {
            if (atomicBoolean.compareAndSet(true, false)) {
                System.out.println("初始化中1");
                System.out.println("初始化中2");
                System.out.println("初始化完毕");
            }
        }

        @Override
        public void run() {
            init();
        }

    }
}
初始化中1
初始化中2
初始化完毕
上一篇下一篇

猜你喜欢

热点阅读