打赏

并发编程锁总结

锁总结

悲观锁

总是假设最坏的情况,每次对数据操作都认为其它数据可能修改。在整个数据处理过程之中,将数据处于锁定状态。

应用:

  1. 数据库的锁机制(读锁、行锁、写锁等),数据库中实现是对数据记录操作前给记录加排他锁。如果获取锁失败,则说明数据库正在修改,则等待或者抛出异常。如果
  2. synchronized的思想也是悲观锁

加锁成功,则获取记录,对其操作,然后事务提交后释放排他锁。

例子:select * from 表 where .. for update;

乐观锁

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

应用:

  1. version方式:一般是在数据表中加上一个数据版本号version字段,表示数据被修改的次数,当数据被修改时,version值会加一。当线程A要更新数据值时,在读取数据的同时也会读取version值,在提交更新时,若刚才读取到的version值为当前数据库中的version值相等时才更新,否则重试更新操作,直到更新成功。
  2. CAS操作方式:即compare and swap 或者 compare and set,涉及到三个操作数,数据所在的内存值,预期值,新值。当需要更新时,判断当前内存值与之前取到的值是否相等,若相等,则用新值更新,若失败则重试,一般情况下是一个自旋操作,即不断的重试

例子:

  1. update table set x=x+1, version=version+1 where id=#{id} and version=#{version};

公平锁和非公平锁

公平锁:表示线程获取锁的顺序是按照线程的锁的时间长短来决定的,就像操作系统中的先来先服务。

非公平锁:不是先来先服务。

应用:

ReentrantLock中提供的公平锁与非公平锁实现,默认是非公平锁(公平锁会带来一定的性能损耗)

公平锁:ReentrantLock pairLock= new ReentrantLock(true)

非公平锁: ReentrantLock pairLock = new ReentrantLock(flase)

例子:

独占锁和共享锁

根据锁的只能被单线程持有还是能被多个线程持有,锁分为独占锁和共享锁。

独占锁,保证任何情况下都只有一个线程获得锁,

共享锁,可以被多个线程持有

应用:独占锁:ReentrantLock(重入锁)

       共享锁:ReentrantReadWriteLock(读写锁)

重入锁

当一个线程要获取一个被其它线程持有的锁的时候,该线程会被阻塞,那么当一个线程再次获取它自己已经获取它自己已经获取的锁的时候是否会被阻塞,如果不被阻塞,那么认为锁是可冲入的,也就是该线程获取了该锁,那么就可以无限制次数哦的进入被该被锁住的代码

当该锁的线程再次获取该锁的时候发现锁的拥有者是自己,就会把计数器加1,当释放锁会减1,当计算器为0时,锁里面的线程标志重置为null,这时候阻塞的线程会被唤醒来竞争后去该锁。

应用:

  1. ReentrantLock
  2. synchronized
posted @ 2018-12-17 04:35  JupiterMouse  阅读(335)  评论(0编辑  收藏  举报