JAVA和Nginx 教程大全

网站首页 > 精选教程 正文

java多线程——锁

wys521 2024-11-23 23:45:49 精选教程 17 ℃ 0 评论

java多线程有两种形式的锁,悲观锁和乐观锁

悲观锁总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁。synchronized、Lock属于悲观锁。Lock有三种实现类:ReentrantLock、ReadLock(读锁)和WriteLock(写锁)。

乐观锁总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁。CAS属于乐观锁。

synchronized 与ReentrantLock对比

相同点:synchronized 与ReentrantLock都用于线程同步锁,都是互斥锁,即某一时刻只允许一个线程共享资源,不管是读数据还是写数据。

不同点:

  • synchronized是内置锁,只要在代码开始的地方加synchronized,代码结束会自动释放。Lock必须手动加锁,手动释放锁。
  • synchronized代码量少,自动化,但扩展性低,不够灵活;ReentrantLock扩展性好,灵活,但代码量相对多。
  • synchronized释放锁:线程执行完毕;线程发生异常;线程进入休眠状态;Lock释放锁:通过unLock方法。
  • synchronized依赖JVM实现,ReentrantLock是JDK实现的。
  • synchronized是非公平锁,ReentrantLock可以指定是公平锁还是非公平锁。所谓的公平锁就是先等待的线程先获取锁。

ReentrantLock与ReentrantReadWriteLock对比

ReentrantReadWriteLock实现了ReadWriteLock接口,ReadWriteLock接口中维护了两个锁:ReadLock(共享锁)和writeLock(排他锁),补充了Lock完成互斥的情况。允许线程同时读取共享资源;如果有一个线程是写线程,那么其他线程就不能读写该资源。即会出现三种情况:读读共享、写写互斥和读写互斥。

CAS

CAS是一种无锁算法,在不使用锁的的情况下实现多线程之间的变量同步。CAS算法涉及到三个操作数

  • 需要读写的内存值V
  • 进行比较的值A
  • 拟写入的新值B

当且仅当V的值等于A时,CAS通过原子方式使用新值B来更新V的值。如果不相等,则重新获取内存地址V 的值,并重新计算想要修改的新值。不断的重试操作。

乐观锁适合读操作多的场景,不加锁的特点能够使其读操作的性能大幅提升。不过乐观锁CAS也存在三大问题:

  1. ABA问题:CAS需要在操作值的时候检查内存值是否发生变化,没有发生变化才会更新内存值。但是如果内存值原来是A,后来变成了B,然后又变成了A,那么CAS进行检查时会发现值没有发生变化,但是实际上是有变化的。ABA问题的解决思路就是在变量前面添加版本号,每次变量更新的时候都把版本号加1。只有检查当前引用等于预期引用并且当前版本号等于预期版本号时,才使用原子方式更新给定的新值。
  2. 如果长时间不成功,会给CPU带来非常大的执行开销。
  3. 只能保证一个共享变量的原子操作。

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表