上文说到了线程安全的互斥同步实现方法,这里说一下非阻塞同步。
非阻塞同步
互斥同步的主要问题是线程阻塞和唤醒所带来的性能问题,所以互斥同步也叫阻塞同步。
说到底,互斥同步是一种悲观锁,悲观锁优势是简单,劣势是性能差;相对应的就是乐观锁,简单来说:先进行操作,如果没有其他线程争用共享数据,那操作就成功了,如果有争用,产生了冲突,再采取补救。这种方式不需要把线程挂起,所以是非阻塞的。
乐观锁的优势是减少了锁建立和释放的次数,劣势是需要“硬件指令集的发展”。因为我们需要对操作和冲突检测另个步骤都具备原子性,这里只能靠硬件来完成。
典型的乐观锁比如CAS,以下是使用CAS操作来避免阻塞同步的一个例子:代码的逻辑很简单,即进行20个自增10000此的操作。
import java.util.concurrent.atomic.AtomicInteger;
public class CASTest{
public static AtomicInteger race = new AtomicInteger(0);
public static void increase(){
race.incrementAndGet();
}
public static final int THREAD_COUNT = 20;
public static void main(String[] args) {
Thread [] threads = new Thread[THREAD_COUNT];
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(new Runnable(){
@Override
public void run() {
for (int j = 0; j < 10000; j++) {
increase();
}
}
});
threads[i].start();
}
while(Thread.activeCount()>1){
Thread.yield();
}
System.out.println(race);
}
}
程序中使用AtomicInteger代替int,程序输出稳定为200000,这要归功于incrementAndGet()方法的原子性。源码如下:
public final int incrementAndGet(){
for(;;){
int current = get();
int next = current +1;
if(compareAndSet(current, next))
return next;
}
}