java并发编程学习13--Atomic数据结构简介

发布时间:2019-11-20 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了java并发编程学习13--Atomic数据结构简介脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

【介绍

JAVA 中无锁的线程安全整数 AtomicInteger,一个提供原子操作的Integer的类。在Java语言中,++ii++操作并不是线程安全的,在使用的时候,不可避免的会用synchronized关键字。而AtomicInteger则通过一种线程安全的加减操作接口。AtomicInteger为什么能够达到多而不乱,处理高并发应付自如呢?这是由硬件提供原子操作指令实现的,这里面用到了一种并发技:CAS。在非激烈竞争的情况下,开销更小,速度更快。
Java.util.con@R_360_834@中实现的原子操作类包括:

AtomicBoolean、AtomicInteger、AtomicIntegerArray、AtomicLong、AtomicReference、AtomicReferenceArray。 

【核心:基于CAS的乐观锁实现

1.悲观锁与乐观锁:

 - 悲观锁(PEssimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。  - 乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于wrITe_condition机制的其实都是提供的乐观锁。     

两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下,即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果经常产生冲突,上层应用会不断的进行retry,这样反倒是降低了性能,所以这种情况下用悲观锁就比较合适。

2.CAS:

CAS就是Compare and Swap的意思,比较并操作。很多的cpu直接支持CAS指令。CAS是项乐观锁技术,当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。

PRivate static final Unsafe unsafe = Unsafe.getUnsafe(); 

【与synchronized与ReentrantLock的比较

  • synchronized
    在资竞争不是很激烈的情况下,偶尔会有同步的情形下,synchronized是很合适的。原因在于,编译程序通常会尽可能的进行优化synchronize,另外可读性非常好,不管用没用过5.0多线程包的程序员都能理解。
  • ReentrantLock:
    ReentrantLock提供了多样化的同步,比如有时间限制的同步,可以被Interrupt的同步(synchronized的同步是不能Interrupt的)等。在资源竞争不激烈的情形下,性能稍微比synchronized差点点。但是当同步非常激烈的时候,synchronized的性能一下子能下降好几十倍。而ReentrantLock确还能维持常态(1.7后synchronized已经优化,性能差距很小)。
  • Atomic:
    和上面的类似,不激烈情况下,性能比synchronized略逊,而激烈的时候,也能维持常态。激烈的时候,Atomic的性能会优于ReentrantLock一倍左右。但是其有一个缺点,就是只能同步一个值,一段代码中只能出现一个Atomic的变量,多于一个同步无效。因为他不能在多个Atomic之间同步。

【例子

package AtomicData;  import java.util.concurrent.atomic.AtomicInteger;  public class Test {      public static void main(String[] args) throws InterruptedException {         Test test = new Test();         MyThread my = new MyThread(test);         for (int i = 0; i < 500; i++) {             Thread t = new Thread(my);             t.start();         }         //等待子线程执行完         Thread.sleep(5000);         System.out.println(test.number);     }      AtomicInteger number = new AtomicInteger(0);     protected void update() {         number.getAndAdd(1);     } } class MyThread implements Runnable {      Test t;      public MyThread(Test t){         this.t =t;     }      @override     public void run() {         t.update();     } }

脚本宝典总结

以上是脚本宝典为你收集整理的java并发编程学习13--Atomic数据结构简介全部内容,希望文章能够帮你解决java并发编程学习13--Atomic数据结构简介所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。