《Java并发编程的艺术》——什么是锁(一)

一 什么是锁

锁,锁是用于控制多个线程访问共享资源的方式。

  1. 是谁在控制呢?
    Synchronized是通过Java对象头中的monitor对象来进行控制,底层通过mutex互斥原语来保证了原子性。那么他可以控制同步代码快、同步方法等。
    Lock接口 则是在AQS同步器是控制,在AQS同步器,是通过volitile 修饰的 int 型状态值来实现线程的可见行性。并通过循环CAS设置状态来保证了原子性。

  2. 控制的共享资源在哪儿
    Synchronized和Lock接口为例子,可以是同步方法、同步代码快。

  3. 用什么样子的方式控制
    Synchronized 获取的锁,其他的线程就获取不到了,是一种独占式的锁。但是lock接口的读写锁实现类里面 又实现了,读锁,即多个线程可以同时获取到锁

  4. 被控制的线程在干什么?
    synchronized 中没有获取到锁的线程,进入了线程等待。而lock接口的不同实现类又有不同的方法,例如在进入了同步队列等待唤醒,或者不停的自旋获取锁。也可以直接返回。
    ,在AQS同步器,是通过volitile 修饰的 int 型状态值来实现线程的可见行性。并通过循环CAS设置状态来保证了原子性。

二 有哪些种类的锁

独占锁和共享锁
概念上可以区分的 独占式和共享式:最具有代表性的就是 ReentrantReadWriteLock ,它内部封装来了两个内部类ReadLock 和 WriteLock两个锁,分别实现了AQS的 独占式同步器和共享式同步器。
共享式获取和独占式获取最主要的区别在于同一个时刻能否有多个线程同时获取到锁状态。
大部分的锁都是独占式的锁,例如Synchronized、ReentrantLock、ReentrantReadWriteLock.WriteLock
而共享锁最具代表的 就是 ReentrantReadWriteLock.ReadLock又是共享式等锁

悲观锁和乐观锁
乐观锁:乐观锁乐观的认为,多线程同步数据时,其他线程不会对数据有任何操作。他并不是一种锁,而是CAS算法
什么是CAS呢?Compare-and-Swap,即比较并替换,也有叫做Compare-and-Set的,比较并设置。
1、比较:读取到了一个值A,在将其更新为B之前,检查原值是否仍为A(未被其他线程改动)。
2、设置:如果是,将A更新为B,结束。如果不是,则什么都不做。
循环重试 CAS就实现了线程的 一定意义上的“串行化”,实现了线程操作的 原子性的
因为整个过程中并没有“加锁”和“解锁”操作,因此乐观锁策略也被称为无锁编程。换句话说,乐观锁其实不是“锁”,它仅仅是一个循环重试CAS的算法而已!
优点:乐观锁适用于写比较少的情况下(多读场景),即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。
缺点:自旋时间长开销大,自旋CAS(也就是不成功就一直循环执行直到成功)如果长时间不成功,会给CPU带来非常大的执行开销。
悲观锁:悲观锁悲观的认为,在进行多线程数据同步时,其他线程一定会进行数据的修改。例如synchronized,lock接口都是悲观锁。我们在使用的适
可重入锁和不可重入锁
可重入与不可重入锁:大家都知道 ReentrantLock 是可重入锁的,那么可重入和不可重入是如何工作的呢?而Synchronized是隐式的支持重进入的。
可重入锁:也有叫秭归锁的,当一个线程获取锁后可以在其内部继续获取锁,并用一个变量记录锁的数量 最具代表的就是 ReentrantLock ,Synchronized也是隐式的可重入锁,这种可重入锁有效的避免了死锁。
不可重入锁:一个线程获取锁后在其内部无法在获取锁,如果一个持有锁的线程 又要去获取同步代码快,就会 进入死锁状态。

公平锁和非公平锁
公平锁和非公平锁 :就是保证了多线程下 各线程获取锁的顺序,也就是等待最长时间的锁优先获取到锁
非公平锁:是无法提供这个保证的。
ReentrantLock 通过构造参数来设置 可重入锁是不是公平的,查看源码可以得知,公平锁比非公平锁多了一个 判断队列是不是或者 或者 当前线程是不是队列头的判断

非公平锁锁是要大于公平锁的,非公平锁效率高于公平锁的原因,因为非公平锁减少了线程挂起的几率,后来的线程有一定几率逃离被挂起的开销。非公平锁虽然可能造成线程饥饿,但是极少的线程切换,保证了更大的吞吐量。

自旋锁和自适应自旋锁
自旋锁:则在Synchronized、AQS同步器中都是广泛应用的。

在AQS同步器中,compareAndSetHead、compareAndSetTail等方法都是通过CAS来实现维护同步同队列等FIFO先进先出原则。compareAndSetWaitStatus则维护着锁的状态。通过CAS自旋可以让线程变得“串性化”。

偏向锁/轻量级锁/重量级锁
具体参考 《Java并发编程的艺术》学习 ——synchornized

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值