CAS机制:Compare And Swap 乐观锁 无所并发,无阻塞并发
核心:
1.内存位置
2.旧的预选值
3.准备设置的值
问题:
1.循环时间长消耗资源大
2.ABA 问题(AtomicStampedReference 原子引用)
3.只能保证一个共享变量的原子问题
synchronized和Lock有什么区别
原始构成
synchronized是关键字属于JVM层面
monitorenter(底层是通过monitor对象来完成,其实wait/notify等方法也依赖monitor对象只有在同步块或者方法中才能调wait/notify等方法,monitorexit退出)
Lock是具体类(java.util.concurrent.locks.Lock)是API层面的锁
使用方法
synchronized 不需要用户去手动释放锁,当synchronized代码执行完成后系统会自动让线程释放对锁的占用
ReentrantLock 需要用户去手动释放锁,若没有主动释放锁,就有可能导致出现死锁现象,需要lock()和unlock()方法配合try/finally语句块来完成。
等待是否可中断
synchronized 不可中断,除非抛出异常或者正常运行完成
ReentrantLock 可以中断,设置超时方法tryLock(long timeout,TimeUit unit,lockInterruptibly()放代码块中,调用interrupt()方法可以中断
加锁是否公平
synchronized 是非公平锁
ReentrantLock 两者都可以,默认非公平锁,构造方法可以传入Boolean值,true为公平锁,false为非公平锁
锁绑定多个条件condition
synchronized 没有
ReentrantLock 用来实现分组唤醒需要唤醒的线程们,可以精确唤醒,而不是像synchronized 要么随机唤醒一个线程要么唤醒全部线程。
————————————————
版权声明:本文为CSDN博主「CodeRemote」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_43813937/article/details/105855369
乐观锁跟悲观锁
乐观锁:在每次操作时,都认为不会对数据进行修改操作,所以不对数据进行上锁。因此多用于读操作很多的地方,不需要进行上锁,提高吞吐量
悲观锁:在每次操作时,都认为会对数据进行修改操作,所以对数据都进行上锁,保证了数据的安全性(即一个进程在修改数据时,其他进程无法对该数据进行操作)
公平锁跟非公平锁
公平锁:多个线程在等待同一个锁时,必须按照申请锁的先后顺序来一次获得锁
非公平锁:多个线程在等待同一个锁时,不会按照申请锁的先后顺序来获得锁
优劣:公平锁保证了每个线程都能获得锁,但是效率很低;非公平锁效率很高,但是不能保证每个线程都能获得锁,有些线程可能会饿死
共享锁和排它锁
共享锁:如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不能加排它锁。获准共享锁的事务只能读数据,不能修改数据
排它锁:如果事务T对数据A加上排它锁后,则其他事务不能再对A加任何类型的锁。获得排它锁的事务即能读数据又能修改数据
偏向锁,轻量级锁和重量级锁
偏向锁:会偏向于第一个访问锁的线程,如果在运行过程中,同步锁只有一个线程访问,不存在多线程争用的情况,则线程是不需要触发同步的,这种情况下,就会给线程加一个偏向锁。如果在运行过程中,遇到了其他线程抢占锁,则持有偏向锁的线程会被挂起,JVM会消除它身上的偏向锁,将锁恢复到标准的轻量级锁
轻量级锁:轻量级锁可以理解为偏向锁的升级版
重量级锁:synchronized,非公平锁,可以对任何一个非Null对象进行上锁
读写锁:ReentrantReadWriteLock 是一个读写锁,读操作加读锁,可以并发读,写操作使用写锁,只能单线程写
死锁:死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,他们都将无法推进下去
产生条件:1.互斥条件:一个资源每次只能被一个进程使用。
2.请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
3.不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺。
4.循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系
解决方法:破坏4种产生条件中的一种即可,即最简单的就是让所有的资源按照一定的顺序进行操作
自旋锁:是指当一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,直到获取到锁才会退出循环
分段锁:ConcurrentHashMap的所使用的的,在jdk1.8被弃用,重新使用synchronized
JVM 使用了锁升级的优化方式,就是先使用偏向锁优先同一线程然后再次获取锁,如果失败,就升级CAS轻量级锁,如果失败就会短暂自旋,防止线程被系统挂起。最后如果以上都失败就升级为重量级锁