synchronized和AQS的区别
- ReentrantLock 显示的获得、释放锁, synchronized 隐式获得释放锁
- ReentrantLock 可响应中断、可轮回, synchronized 是不可以响应中断的,为处理锁的不可用性提供了更高的灵活性
- ReentrantLock 是 API 级别的, synchronized 是 JVM 级别的
- ReentrantLock 可以实现公平锁
- ReentrantLock 通过 Condition 可以绑定多个条件
- 底层实现不一样, synchronized 是同步阻塞,使用的是悲观并发策略, lock 是同步非阻塞,采用的是乐观并发策略
- Lock 是一个接口,而 synchronized 是 Java 中的关键字, synchronized 是内置的语言实现。
- synchronized 在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而 Lock 在发生异常时,如果没有主动通过 unLock()去释放锁,则很可能造成死锁现象,因此使用 Lock 时需要在 finally 块中释放锁。
- Lock 可以让等待锁的线程响应中断,而 synchronized 却不行,使用 synchronized 时,等待的线程会一直等待下去,不能够响应中断。
- 通过 Lock 可以知道有没有成功获取锁,而 synchronized 却无法办到。
- Lock 可以提高多个线程进行读操作的效率,既就是实现读写锁等
synchronized和AQS的共同点
- 1.都是用来协调多线程对共享对象、变量的访问
- 都是可重入锁,同一线程可以多次获得同一个锁
- 都保证了可见性和互斥性
Synchronized 核心组件
- Wait Set:哪些调用 wait 方法被阻塞的线程被放置在这里;
- Contention List: 竞争队列,所有请求锁的线程首先被放在这个竞争队列中;
- Entry List: Contention List 中那些有资格成为候选资源的线程被移动到 Entry List 中;
- OnDeck:任意时刻, 最多只有一个线程正在竞争锁资源,该线程被成为 OnDeck;
- Owner:当前已经获取到所资源的线程被称为 Owner;
- !Owner:当前释放锁的线程
synchronized底层依赖操作系统 Mutex Lock
Synchronized的流程
-
0.先获取偏向锁,不行再自旋锁,获取到锁就是轻量级锁,如果自旋获取不到锁就是重量级锁。重量级锁的流程就是如下:
-
1.竞争的线程进入contentionList,并迁移部分的竞选者到EntryList,此举是为了降低竞争(防止所有线程同时醒来去CAS获取锁)
-
2.获取锁的线程会在unlock的时候唤醒entryList中的线程,该线程就是onDeck,注意并不是把锁给onDeck,而是允许他
和其他刚准备来获取锁的线程进行竞争(其他已经进入contentionList的线程不会去),这就是非公平性。 -
3.onDeck获取成功则会变为Owner线程,如果owner线程被wait方法阻塞,则转移到WaitSet队列,该队列
会被notify和notifyAll唤醒并重新加入到entryList -
4.线程再进入ContentionList时候 会先自旋获取锁,获取不到就进入contentionList,这也是一个不公平的地方
-
5.每个对象都有一个monitor对象,加锁就说竞争monitor对象。
-
6.优化后的偏向锁和轻量级锁都是对对象头操作,不需要经过操作系统加锁。
上下文
- 是指某一时间点 CPU 寄存器和程序计数器的内容。
寄存器
- 是 CPU 内部的数量较少但是速度很快的内存(与之对应的是 CPU 外部相对较慢的 RAM 主内
存)。寄存器通过对常用值(通常是运算的中间值)的快速访问来提高计算机程序运行的速
度.
寄存器和高速缓存的区别
- CPU要取数据,处理数据,都要放到寄存器处理。一般寄存器不用太大,它只要存放指令一次操作的数据就够了。
高速缓存是内存的部分拷贝,因为高速缓存速度快,把常用的数据放这里可以提高速度。
高速缓存一般不能被程序直接更改,它由硬件自己处理。程序直接读写CPU的寄存器,来完成操作。
一般两者都集成在CPU上。
上下文切换的活动
- 挂起一个进程,将这个进程在 CPU 中的状态(上下文)存储于内存中的某处。
- 在内存中检索下一个进程的上下文并将其在 CPU 的寄存器中恢复。
- 跳转到程序计数器所指向的位置(即跳转到进程被中断时的代码行),以恢复该进程在程序
中。
- 跳转到程序计数器所指向的位置(即跳转到进程被中断时的代码行),以恢复该进程在程序
网友评论