MacTalk 2017-12-09
原子类在具有逻辑的情况下输出结果也具有随机性
package com.cky.thread; import java.util.concurrent.atomic.AtomicLong; /** * Created by edison on 2017/12/9. */ public class MyService { public static AtomicLong ai= new AtomicLong(); public void addNum() { System.out.println(Thread.currentThread().getName() +" 加了100之后的值是"+ ai.getAndAdd(100)); ai.getAndAdd(1); } }
package com.cky.thread; /** * Created by edison on 2017/12/9. */ public class MyThread extends Thread{ private MyService service; public MyThread(MyService service) { this.service =service; } @Override public void run() { super.run(); service.addNum(); } }
package com.cky.test; import com.cky.thread.MyService; import com.cky.thread.MyThread; /** * Created by edison on 2017/12/9. */ public class Run { public static void main(String[] args) { try { MyService myService = new MyService(); MyThread[] myThreads = new MyThread[5]; for (int i = 0; i < myThreads.length; i++) { myThreads[i] = new MyThread(myService); } for (int i = 0; i < myThreads.length; i++) { myThreads[i].start(); } Thread.sleep(1000); System.out.println(myService.ai.get()); } catch (InterruptedException e) { e.printStackTrace(); } } }
Thread-1 加了100之后的值是0 Thread-4 加了100之后的值是400 Thread-2 加了100之后的值是300 Thread-3 加了100之后的值是200 Thread-0 加了100之后的值是100 505
结果分析:
打印顺序出错了,应该每次加100在加一次1,出现这样的情况原因是addAndGet()方法是原子的,但方法和方法直接的调用却不是原子的
解决方案同步
package com.cky.thread; import java.util.concurrent.atomic.AtomicLong; /** * Created by edison on 2017/12/9. */ public class MyService { public static AtomicLong ai= new AtomicLong(); synchronized public void addNum() { System.out.println(Thread.currentThread().getName() +" 加了100之后的值是"+ ai.getAndAdd(100)); ai.getAndAdd(1); } }
Thread-1 加了100之后的值是0 Thread-3 加了100之后的值是101 Thread-4 加了100之后的值是202 Thread-0 加了100之后的值是303 Thread-2 加了100之后的值是404 505