Java中的锁介绍: 公平非公平锁、递归锁、自旋锁、读写锁(互斥锁)
每个线程在获取锁时会查看此锁维护的等待队列,若为空或者当前线程是等待队列中的第一个,就占有锁,否则就加入等待队列 多线程按申请锁的顺序来获取锁,顺序策略(队列先来后到)
上来就直接尝试占有锁,若尝试失败,则采用公平锁的方式 多线程获取锁的顺序并不是按照申请锁的顺序,高并发情况下,可能会造成优先级反转或饥饿现象 ReentrantLock默认非公平,synchronized是一种非公平锁
反转:并不是按照顺序来获取锁,允许加塞 饥饿:线程一直获取不到锁
ReentrantLock/synchronized默认可重入锁 同一个线程外层函数获取锁的时候,在进入内层方法会自动获取锁(在同步方法中调用同步方法会自动获取锁,因为是同一把锁)
public synchronized void method1() { method2(); } public synchronized void method2(){ } Lock lock=new ReentrantLock(); public void M() { lock.lock(); lock.lock(); try { System.out.println(); }finally { lock.unlock(); lock.unlock(); } }Lock加锁在finally中解锁防止线程抛出异常 锁可以重复加,但注意加锁几次解锁几次(若加多次,关闭次数不对应,编译通过,运行出现阻塞)
尝试获取锁的线程不会立即阻塞,而是采用循环的方式去获取锁
优:循环获取直到成功为止,没有类似的wait阻塞(减少线程上下文切换的消耗) 缺:循环会消耗CPU,若是一直不能获取锁,系统性能会下降
该锁可被多个线程所持有,提高了并发性
该锁只能被一个线程所持有 (ReentrantLock、synchronized)
ReentrantReadWriteLock读锁是共享,写锁是独占 读写锁:读-读能共存,读-写不能共存,写-写不能共存
总结:synchronized是重锁, 并发性低,要有读写分离的思想