无锁工具类:原子类

累加器例子:add10K() 这个方法不是线程安全的,问题就出在变量 count 的可见性和 count+=1 的原子性上

1.可见性问题可以用 volatile 来解决,

2.原子性问题我一直都是采用的互斥锁。
public class Test {
  long count = 0;
  void add10K() {
    int idx = 0;
    while(idx++ < 10000) {
      count += 1;
    }
  }
}

 

对于简单的原子性问题,还有一种无锁方案:

1.将原来的 long 型变量 count 替换为了原子类 AtomicLong,

2.原来的 count +=1 替换成了 count.getAndIncrement(),

3.仅需要这两处简单的改动就能使 add10K() 方法变成线程安全的
public class Test {
  AtomicLong count = 
    new AtomicLong(0);
  void add10K() {
    int idx = 0;
    while(idx++ < 10000) {
      count.getAndIncrement();
    }
  }
}

 

无锁方案优势:性能

1.互斥锁方案为了保证互斥性,
    1) 需要执行加锁、解锁操作,而加锁、解锁操作本身就消耗性能;
    2) 同时拿不到锁的线程还会进入阻塞状态,
    3) 进而触发线程切换,线程切换对性能的消耗也很大。 

2.相比之下,无锁方案
    1) 完全没有加锁、解锁的性能消耗,
    2)同时还能保证互斥性

 

getAndIncrement() 方法内部就是基于 CAS 实现的:

 

posted @ 2020-11-07 16:13  天天大傻猫  Views(93)  Comments(0Edit  收藏  举报