synchronized和Lock都是悲观锁,它们认为当使用数据的时候必定有其它线程来修改,因此在获取数据的时候就会加锁,确保不会被其它线程修改。数据库
synchronized代码块:微信
public synchronized void update() { //同步资源 }
Lock代码块:多线程
public void update() { Lock lock = new ReentrantLock(); lock.lock(); try { //同步资源 } finally { lock.unlock(); } }
乐观锁,它认为使用数据的时候不会有别的线程来修改数据,因此不会加锁。只要在自身要进行update操做的时候,才会去判断以前的数据是否被别的线程修改了。若是没有被修改则会修改为功,相反则会修改不成功。这里最典型的是java.util.concurrent并发包中的递增操做就经过CAS自旋实现的。并发
CAS代码块app
public class TestLock { AtomicInteger atomicInteger = new AtomicInteger(0); public int add() { return atomicInteger.incrementAndGet(); }}
什么是CAS,CAS的全称为Compare And Swap(比较与交换),是一种无锁算法。在不使用锁(没有线程被阻塞)的状况下实现多线程之间的变量同步。性能
总结: 这里咱们能够得出悲观锁适合写操做多的场景,先加锁能够保证写操做时数据正确。乐观锁适合读操做多的场景,不加锁的特色可以使其读操做的性能大幅提高。不过从jdk1.8以后java已经对synchronized作了优化,性能上有了大幅度的提高。可是乐观锁CAS,也不是那么十全十美,目前它存在三个三大问题。大数据
ABA问题(JDK1.5以后已有解决方案):CAS须要在操做值的时候检查内存值是否发生变化,没有发生变化才会更新内存值。可是若是内存值原来是A,后来变成了B,而后又变成了A,那么CAS进行检查时会发现值没有发生变化,可是其实是有变化的。ABA问题的解决思路就是在变量前面添加版本号,每次变量更新的时候都把版本号加一,这样变化过程就从“A-B-A”变成了“1A-2B-3A”。优化
循环时间长开销大:CAS操做若是长时间不成功,会致使其一直自旋,给CPU带来很是大的开销。
只能保证一个共享变量的原子操做(JDK1.5以后已有解决方案):对一个共享变量执行操做时,CAS可以保证原子操做,可是对多个共享变量操做时,CAS是没法保证操做的原子性的。
你们能够把1和3的解决方案告诉我吗?
也能够点击阅读原文跳转。