• java多线程系列5 atomic简介


    先看一个例子,AtomicInteger 实现的线程安全的累加器

    public class AtomicIntTest {
    	public static void main(String[] args) {
    		AddRunnable addRunnable = new AddRunnable();
    		Thread myThread1 = new Thread(addRunnable);
    		Thread myThread2 = new Thread(addRunnable);
    		myThread1.start();
    		myThread2.start();
    		try {
    			myThread1.join();
    			myThread2.join();
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    
    		System.out.println(addRunnable.count);
    	}
    
    }
    
    class AddRunnable implements Runnable {
    	AtomicInteger count = new AtomicInteger();
    
    	@Override
    	public void run() {
    		for (int i = 0; i < 100000; i++) {
    			count.incrementAndGet();
    		}
    	}
    
    }
    

    AtomicInteger源码分析

           下面通过AtomicInteger的源码来看一下是怎么在没有锁的情况下保证数据正确性。首先看一下incrementAndGet方法的实现

          

    public final int incrementAndGet() {  
        for (;;) {  
            int current = get();  
            int next = current + 1;  
            if (compareAndSet(current, next))  
                return next;  
        }  
    }  
    
    
    public final boolean compareAndSet(int expect, int update) {     
        return unsafe.compareAndSwapInt(this, valueOffset, expect, update);  
    }  
    

      注意::valueOffset叫做 偏移量 我们知道valueOffset指向的地址对应的值就是原始变量的值 执行逻辑就是 expect 和valueOffset 比较 相同 就替换成 update 不同继续循环

     

     总结:

         

    虽然基于CAS的线程安全机制很好很高效,但要说的是,并非所有线程安全都可以用这样的方法来实现,这只适合一些粒度比较小,型如计数器这样的需求用起来才有效,否则也不会有锁的存在了。实际来发中,用锁的情况还是较多。

    并发越高,失败的次数会越多,CAS如果长时间不成功,会极大的增加CPU的开销。(毕竟死循环嘛) 因此CAS不适合竞争十分频繁的场景。

    3 CAS只能保证一个共享变量的原子操作。当对多个共享变量操作时,CAS就无法保证操作的原子性,这时就可以用锁,或者把多个共享变量合并成一个共享变量来操作。使用AtomicReference。

  • 相关阅读:
    在普通类中调用service
    layui util 工具时间戳转换
    最大值
    药房管理
    线段树2
    线段树1
    Dijkstra
    最大值最小化
    图的M 着色问题
    取余运算
  • 原文地址:https://www.cnblogs.com/javabigdata/p/6842292.html
Copyright © 2020-2023  润新知