synchronized详解 乐观锁和悲观锁 volatile关键字 无锁编程CAS CPU锁类型

2016-05-19 20:54:00
admin
原创 1170
摘要:synchronized详解 乐观锁和悲观锁 volatile关键字 无锁编程CAS CPU锁类型

一、synchronized详解

1、synchronized(obj)锁对象是obj,相当于互斥锁,只有一个线程可以访问;

2、synchronized修饰方法相当于synchronized(this),比如public synchronized void method();

3、synchronized修饰静态方法时锁对象是类;

4、synchronized操作无法被中断,除非获取到锁;

5、synchronized是重入锁,持有锁的线程可以访问其它同步方法;

6、synchronized是非公平锁,多个线程同时获取锁,获取到锁的顺序不保证;

7、示例代码:Syncn.java


public class Syncn {

public void run1() {
synchronized(this) {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " synchronized loop " + i);
}
}
}

public void run2() {
synchronized(this) {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " synchronized loop " + i);
}
}
}

public static void main(String[] args) {
final Syncn syncn = new Syncn();
Thread a = new Thread(new Runnable(){public void run() {syncn.run1();}}, "a");
Thread b = new Thread(new Runnable(){public void run() {syncn.run2();}}, "b");
a.start();
b.start();

}
}


二、乐观锁和悲观锁 

独占锁是一种悲观锁,synchronized是一种独占锁,只有确保其它线程不会造成干扰的情况下执行,会导致其它所有需要锁的线程挂起,等待持有锁的线程释放锁;而更加有效的锁就是乐观锁,乐观锁每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。


三、volatile关键字

1、C或者C++禁止编译器优化volatile修饰的变量,每次访问都直接重内存读取,不使用寄存器;

2、JAVA禁止编译器优化volatile修饰的变量,每次访问直接从堆内存读取,不使用线程变量副本;

3、示例:C语言volatile int value,JAVA语言private volatile int value;


四、无锁编程CAS

1、CAS:Compare and Swap,中文意思是"比较并交换";
2、java.util.concurrent包中借助CAS实现了区别于synchronized同步锁的一种乐观锁;

3、无锁编程只保证单个读和写操作的原子性,并不保证组合操作的原子性;


硬件支持CAS,LL/SC, atom read-modify-write:

如果CPU提供了Load-Link/Store-Conditional这对指令,则就可以轻松实现变量的CPU级别无锁同步;
LL [addr],dst:从内存[addr]处读取值到dst;
SC value,[addr]:对于当前线程,自从上次的LL动作后内存值没有改变,就更新成新值;

软件实现CAS,CPU没有实现LL/SC这对指令,那么就需要寻找软件算法,比如CAS。


CAS缺陷1,ABA问题(JAVA的AtomicStampedReference可以解决此问题):

线程A执行cas(1,2),还没执行完成就被抢占;

线程B执行cas(1,2),cas(2,1);

线程A继续执行,发现条件成立执行成功,但实际上值中间已经被修改过;

CAS缺陷2,循环时间长开销大。

CAS缺陷3,只能保证一个共享变量的原子操作(AtomicReference可以解决此问题)。


五、CPU锁类型

1、基本操作的原子性,单处理器对同一缓存行的16/32/64位操作是原子的;

2、总线锁机制,处理器之间访问一块共享内存时将顺序执行,先到的CPU先执行,后到的CPU被阻塞;

3、缓存锁机制,比总线锁开销小,但使用场景受限;

发表评论
评论通过审核之后才会显示。