多线程常见锁的策略

目录

一、多线程常见锁的策略

1、乐观锁和悲观锁

(1)乐观锁的解释

(2)悲观锁的解释 

(3)两种策略的事例 

(4)乐观锁检测数据冲突

2、读写锁

(1)读写锁的介绍

 (2)java中的读写锁

3、重量级锁和轻量级锁 

(1)重量级锁

(2)轻量级锁

 4、自旋锁

5、公平锁和非公平锁


一、多线程常见锁的策略

1、乐观锁和悲观锁

(1)乐观锁的解释

假设数据一般情况下不会产生并发冲突,所以在数据进行提交更新的时候,才会正式对数据是否产生并 发冲突进行检测,如果发现并发冲突了,则让返回用户错误的信息,让用户决定如何去做。

(2)悲观锁的解释 

总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁。

(3)两种策略的事例 

当线程冲突不严重时,可以采用乐观锁策略来避免多次的加锁和释放锁操作

当线程冲突很严重时,可以采用悲观锁加锁来避免线程频繁访问共享数据带来的CPU空转问题

(4)乐观锁检测数据冲突

乐观锁并不是真正的把线程阻塞了,乐观锁的实现可以引入“版本号”来解决问题 

此时线程2的操作策略:

    ●直接报错,线程2退出,不写会主内存

    ●从主内存中读写最新的值50以及版本号2,然后再次执行-20操作=30,然后再重新写回主内存

上述图示的核心就是,线程能否成功刷新主内存的值取决于

      工作内存中的版本号==主内存中的版本号时才可以更新,更新成功后,同步刷新自己的版本号和主内存的版本号,即为更新成功

2、读写锁

(1)读写锁的介绍

    多线程之间,数据的读取方之间不会产生线程安全问题,但数据的写入方互相之间以及和读者之间都需 要进行互斥。如果两种场景下都用同一个锁,就会产生极大的性能损耗。所以读写锁因此而产生。

    读写锁(readers-writer lock),看英文可以顾名思义,在执行加锁操作时需要额外表明读写意图,读者之间并不互斥,而写者则要求与任何人互斥。

一个线程对于数据的访问, 主要存在两种操作:

●读数据 和 写数据.

●两个线程都只是读一个数据, 此时并没有线程安全问题. 直接并发的读取即可.

●两个线程都要写一个数据, 有线程安全问题,就只有一个线程可以获得写锁,其余线程阻塞

● 一个线程读另外一个线程写, 也有线程安全问题,当写线程结束读线程才可以继续

读写锁多用于线程基本都在读数据,写数据少的情况

 (2)java中的读写锁

读写锁就是把读操作和写操作区分对待.

Java 标准库提供了 ReentrantReadWriteLock 类, 实现了读写锁.                    ●ReentrantReadWriteLock.ReadLock 类表示一个读锁. 这个对象提供了 lock / unlock 方法进行 加锁解锁.

●ReentrantReadWriteLock.WriteLock 类表示一个写锁. 这个对象也提供了 lock / unlock 方法进行加锁解锁.

其中, 读加锁和读加锁之间, 不互斥. 写加锁和写加锁之间, 互斥. 读加锁和写加锁之间, 互斥.

3、重量级锁和轻量级锁 

(1)重量级锁

    需要操作系统和硬件的支持,线程获取重量级锁进入阻塞状态(依赖操作系统,频繁在用户态和内核态切换,开销非常之大)。

   假如说去银行办理业务,用户态就是在窗口外自己去处理业务,而内核态就是需要在窗口内部需要工作人员进行协助办理业务,当某个业务需要频繁在用户态和内核态之间频繁切换(也就是不停的在外部窗口和工作人员之间跑来跑去,就会非常的耗费时间)

(2)轻量级锁

   尽量在用户态执行操作,线程不阻塞,不会进行状态的切换

   假如说在银行办理业务时,当前业务只需要再外部窗口就可以全部处理完毕,不需要来回跑路,就可以省去一大部分时间,节省开销。

 4、自旋锁

轻量级锁的常用实现就是自旋锁

按之前的方式,线程在抢锁失败后进入阻塞状态,放弃 CPU,需要过很久才能再次被调度. 但实际上, 大部分情况下,虽然当前抢锁失败,但过不了很久,锁就会被释放。没必要就放弃 CPU. 这个 时候就可以使用自旋锁来处理这样的问题.

while (抢锁(lock) == 失败) {}

如果获取锁失败, 立即再尝试获取锁, 无限循环, 直到获取到锁为止. 第一次获取锁失败, 第二次的尝试会在极短的时间内到来. 一旦锁被其他线程释放, 就能第一时间获取到锁.

5、公平锁和非公平锁

公平锁: 遵守 "先来后到". B 比 C 先来的. 当 A 释放锁的之后, B 就能先于 C 获取到锁.

非公平锁: 不遵守 "先来后到". B 和 C 都有可能获取到锁.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值