1

各种方法

1、synchronized方法。

public synchronized void save(){}

2、synchronized代码块。

synchronized(object){ 
}

3、使用重入锁(ReenreantLock)

public void save(int money) {
    lock.lock();
    try {
        account += money;
    } finally {
        lock.unlock();
    }
}

4、使用阻塞队列,同步Map(LinkedBlockingQueue,ConcurrentHashMap等)

5、使用原子变量(AtomicInteger等)

各种原理

独占锁:是一种悲观锁,会导致其它所有需要锁的线程挂起,等待持有锁的线程释放锁。
乐观锁:每次不加锁,假设没有冲突就去完成某项操作,如果因为冲突失败就重试,直到成功为止。

CAS:Compare and Swap,典型的乐观锁,使用Cpu的lock cmpxchg指令进行操作。CAS的底层类为Unsafe,Unsafe通过调用JNI(Java Native Interface)代码,在C语言的compareAndSwapInt函数中嵌入汇编指令进行实现,做到了处理器级别的同步。java.util.concurrent包的所有类都基于CAS。

图片描述
注:volatile保证可见性。参见https://segmentfault.com/a/11...

CAS也有几个缺点:

1、ABA问题,由AtomicStampedReference来解决,即给数据加版本信息。
2、循环时间长开销大。
3、只能保证一个共享变量的原子操作,由AtomicReference来解决,即将多个基本变量整合为一个对象。

总结:

synchronized:
所有对象都自动含有单一的锁,JVM负责跟踪对象被加锁的次数。如果一个对象被解锁,其计数变为0。在任务(线程)第一次给对象加锁的时候,计数变为1。每当这个相同的任务(线程)在此对象上获得锁时,计数会递增。只有首先获得锁的任务(线程)才能继续获取该对象上的多个锁。每当任务离开时,计数递减,当计数为0的时候,锁被完全释放。synchronized就是基于这个原理,同时synchronized靠某个对象的单一锁技术的次数来判断是否被锁,所以无需(也不能)人工干预锁的获取和释放。
实际上synchronized作用于方法时,锁住的是“this”,作用于静态方法/属性时,锁住的是存在于永久带的CLASS,相当于这个CLASS的全局 锁,锁作用于一般对象时,锁住的是对应代码块。在HotSpot中JVM实现中,锁有个专门的名字:对象监视器。
jdk1.6之前,synchronized是通过对象内部的一个叫做监视器锁(monitor)来实现的。但是监视器锁本质又是依赖于底层的操作系统的Mutex Lock来实现的。而操作系统实现线程之间的切换这就需要从用户态转换到核心态,这个成本非常高,状态之间的转换需要相对比较长的时间,这就是为什么Synchronized效率低的原因。然而,1.6之后,synchronized已经被做了CAS的优化:具体是这样的,当执行到synchronized代码块时,先对对象头的锁标志位用lock cmpxchg的方式设置成“锁住“状态,释放锁时,在用lock cmpxchg的方式修改对象头的锁标志位为”释放“状态,写操作都立刻写回主内存。JVM会进一步对synchronized时CAS失败的那些线程进行阻塞操作(调用操作系统的信号量)(此段来摘自别处)。也就是先CAS操作,不行的话继而阻塞线程。

ReentrantLock:
Lock不同于synchronized面向对象,它基于栈中的框架而不是某个具体对象,所以Lock只需要在栈里设置锁的开始和结束 (lock和unlock)的地方就行了(人工必须标明),不用关心框架大小对象的变化等等。这么做的好处是Lock能提供无条件的、可轮询的、定时的、 可中断的锁获取操作,相对于synchronized来说,synchronized的锁的获取是释放必须在一个模块里,获取和释放的顺序必须相反,而Lock则可以在不同范围内获取释放,并且顺序无关。
ReentrantLock提供了多样化的同步,比如有时间限制的同步,可以被Interrupt的同步(synchronized的同步是不能Interrupt的)等。lock是通过代码实现的,要保证锁一定会被释放,就必须将unlock()放到finally{}中。

最后,Atomic无疑是最快的,其次是ConcurrentHashMap等。在较高的并发下,几种方法性能差不多,而在较低并发下,区别就显现出来了,其中synchronized比Lock来的快,基本是两倍的关系。


怒放的生命
22 声望1 粉丝

« 上一篇
jvm调优
下一篇 »
volatile详解