1、线程要不要锁住同步资源?乐观锁VS悲观锁
悲观锁在获取数据的时候会先加锁,确保数据不被修改。Synchronized和Lock都是悲观锁。
乐观锁在更新数据的时候判断之前线程有没有更新这个数据,如果没有更新,当前线程修改的数据成功写入。乐观锁通过无锁编程实现,采用CAS算法,Java原子类种的递增操作就是CAS自旋实现的。
CAS有三大问题
ABA问题
循环时间长开销大
只能保证一个共享变量的原子操作
2、自旋锁 VS 适应性自旋锁
自旋锁适应场景是同步资源锁定时间很短,为了一小段时间切换线程得不偿失,让获取锁失败的线程不放弃CPU执行,等待持有锁的线程很快释放。
自旋锁本身是有缺点的,它不能代替阻塞.自旋锁虽然避免线程切换,但是占用处理器时间.锁占用时间很短,自旋等待效果就会非常好.
适应性自旋锁意味着自旋的时间不再固定,由前一次在同一个锁上的自旋时间以及锁的拥有者的状态来决定.如果线程自旋成功获取过锁,并且持有锁的线程正在运行,那么虚拟机会认为自旋成功概率大,会让线程自旋长一些时间.如果自旋很少成功获取过锁,则可能直接阻塞线程.
3、无锁 VS 偏向锁 VS 轻量级锁 VS 重量级锁
Java对象头
synchronized是悲观锁,在操作资源之前需要给同步资源先加锁,锁就存在Java对象头里.HotSpot对象头包含两部分: Mark Word(标记字段),Klass Pointer(类型指针)
Mark Word存储对象的Hash Code,分代年龄,锁标志位信息。
Klass Point:对象指向类元数据的指针,确定类的实例的指针。
Monitor
Monitor是线程私有的数据结构,每个线程都有一个可用monitor record列表,同时还有一个全局的可用列表。每一个锁住的对象都会和一个monitor关联。
Synchronized通过Monitor来实现线程同步,Monitor是依赖于底层的操作系统的互斥锁mutex Lock实现的线程同步。通过Mutex Lock实现的锁称为重量级锁。
无锁
:CAS原理就是无锁的实现。
偏向锁
:是指一段代码一直被一个线程访问,那么该线程会自动获取锁,降低获取锁的代价。
轻量级锁
:是指锁是偏向锁的时候,被另外的线程访问,偏向锁会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,从而提高性能。
重量级锁
:当对象处于轻量级锁的状态,对象头被多个线程竞争修改,出现多个线程竞争锁,轻量级锁升级为重量级锁,重量级锁是同步系统的互斥锁。
4、公平锁 VS 非公平锁
公平锁按照线程的申请锁的顺序来获取锁,线程直接插入到队列中排队,队列中第一个线程才能获取锁。公平锁的优点不会饿死,缺点是效率相比非公平锁会低一些。
5、可重入锁 VS 非可重入锁
可重入锁指同一个线程可以多次获取方法中的锁。优点可以避免死锁。
ReentrantLock Synchronized都是可重入锁。
6、独占锁 VS 共享锁
ReentrantLock是独占锁,锁一次只能被一个线程持有。
共享锁指锁可以被多个线程持有。
网友评论