并发锁的理解

最近在看高并发,学习的路上随笔记录,方便以后查阅。
学习并发前,先搞清楚锁的概念 : 悲观锁和乐观锁,公平锁和非公平锁,独占锁和共享锁,可重入锁,自旋锁

 1. 悲观锁和乐观锁:
      悲观锁是在数据被外界修改持保守态度,认为数据很容易被其他线程修改,所以在数据处理前先对数据进行加锁,并在整个数据处理过程中,使数据处于锁定状态。

    乐观锁是相对于悲观锁来说的,认为数据在一般情况下不会造成冲突,所以在访问记录前不会加排它锁,而是在进行数据提交更新的时候,才会对数据冲突进行检测。


    乐观锁不会使用数据库锁机制,一般在表中添加 timeStamp/version字段,或者业务状态来实现,乐观锁只是在提交时才锁定,所以不会产生死锁。

     主要区别: 对数据处理分三步: 1. 先读取数据库中的数据;2.对取出的数据进行修改;3:把修改的数据更新到数据库。
           悲观锁会在第一步前加排它锁,同一时间只能有一个线程执行成功,其他线程则会等待;有可能造成死锁。
          乐观锁 只会在第三步校验数据是否被其他线程更改。不会造成死锁。

2. 公平锁和非公平锁:
    主要根据线程获取锁的抢占机制来分的;公平锁表示线程获取锁的顺序是按照线程请求锁的时间早晚来决定的,即最早请求锁的线程将最先获取到锁。 
   非公平锁则是在运行时闯入的,先来的不一定先得。
 
   ReentrantLock  lock = new ReentrantLock(true);

  参数true为公平锁,false为非公平锁, 默认不传参为非公平锁。

   在没有公平锁需求的前提下尽量使用非公平锁,因为公平锁会带来性能开销。

3. 独占锁和共享锁:
   主要根据锁只能被单个线程持有还是能被多个线程共同持有来分的;独占锁保证在任何时候都只能有一个线程得到锁; 如: ReentrantLock 就是以独占锁方式实现的。 而共享锁可以同时有多个线程持有。如: ReadWriteLock读写锁,他允许一个资源被多个线程同时进行读写操作。

   独占锁是一种悲观锁,共享锁是一种乐观锁!

4.可重入锁
    当一个线程要获取一个被其他线程持有的独占锁时,该线程会被阻塞,那么当一个线程再次获取它自己已经获取的锁时是否会被阻塞呢? 如果不被阻塞,那么我们说该锁时可重入的。也就是只要该线程获取了该锁,那么就可以多次的进入被该锁锁住的代码。

    synchronized内部锁是可冲入锁。 可重入锁原理是在锁的内部维护一个线程标识,用来标识该线程目前被哪个线程占用,然后关联一个计数器。一开始计数器值为0,说明该锁没有被任何线程占用。当一个线程获取了该锁时,计数器值会变成1,这时其他线程获取该锁时会被阻塞挂起;但是当获取该锁的线程再次获取该锁时,发现拥有者是他自己,就会把计数器值 +1 ,释放后计数器值 -1。 当计数器值为0时,锁里的线程标识被重置为null,这时被阻塞的线程会被唤醒来竞争获取锁。

5. 自旋锁:
    在当前线程获取锁时,如果发现锁已被其他线程占用,并不会马上阻塞自己,在不放弃CPU使用权的情况下,多次尝试获取(默认10次,可以通过-XX:PreBlockSpinsh参数设置),很有可能在后面尝试几次中其他线程已经释放了锁。
   自旋锁是使用CPU时间换取线程阻塞与调度的开销。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值