• java锁有哪些类(转)


    转载来源:http://www.cnblogs.com/lxmyhappy/p/7380073.html

    1Java都有哪些锁?

    • 公平锁/非公平锁
    • 可重入锁
    • 独享锁/共享锁
    • 互斥锁/读写锁
    • 乐观锁/悲观锁
    • 分段锁
    • 偏向锁/轻量级锁/重量级锁
    • 自旋锁

    Java实现锁有两种语法,一种是synchronized语句,另外一种是reentrantlock关键字。上面是很多锁的名词,这些分类并不是全是指锁的状态,有的指锁的特性,有的指锁的设计,下面总结的内容是对每个锁的名词进行一定的解释

    公平锁/非公平锁

    公平锁指多个线程按照申请锁的顺序获得锁。

    非公平锁指多个线程获得锁的顺序不按照申请顺序。

    Java reentranthlock通过构造函数来指定锁是公平还是非公平,默认是非公平锁,对于synchronized而言,也是一种非公平锁。

    非公平锁优点在于吞吐量比公平锁大。

    可重入锁

    可重入锁又叫递归锁,是指同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁。举例如下:

    synchronized void setA() throws Exception{
        Thread.sleep(1000);
        setB();
    }
    synchronized void setB() throws Exception{
        Thread.sleep(1000);
    }

    Java reentrantlock是一个可重入锁。上面的代码就是一个可重入锁的一个特点,如果不是可重入锁的话,setB可能不会被当前线程执行,可能造成死锁

    Synchronized也是一个可重入锁。

    可重入锁的优点是可以一定程度避免死锁。

    独享锁/共享锁

    顾名思义,独享锁是指该锁一次只能被一个线程所持有,共享锁可以被多个线程所持有。

    Java reentrantlock是一个独享锁,但是对于lock的另一个实现readwritelock,其读锁是一个共享锁,写锁是一个独享锁。

    对于synchronized是一个独享锁。

    互斥锁/读写锁

    上边说的独享锁和共享锁是一种广义的说法,互斥锁和读写锁就是具体实现。

    互斥锁在Java中具体实现就是reentrantlock

    读写锁在Java中的具体实现就是readwritelock

    乐观锁/悲观锁

    乐观锁和悲观锁不是指具体的锁类型,而是对于看待并发编程中加锁问题的角度。

    悲观锁认为,对于一个数据的并发操作,一定会改变数据,即使实际上数据没被改变,但是也悲观的认为被改变的可能性比较大,一定要加锁,不加锁早晚要出问题。

    乐观锁认为,对于一个数据的并发操作,是不会改变数据的,不加锁也不会出问题。

    乐观锁指java中的无所编程,适合读操作非常多的场景。

    悲观锁就是指java中,适合并发下写非常多的场景。

    自旋锁

    java中,自旋锁是指常识获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,当循环条件被其他线程改变时,才能进入临界区。这样的好处是减少线程上下文切换的消耗,缺点是会消耗CPU

    public class SpinLock {
    
      private AtomicReference<Thread> sign =new AtomicReference<>();
    
      public void lock(){
        Thread current = Thread.currentThread();
        while(!sign .compareAndSet(null, current)){
        }
      }
      public void unlock (){
        Thread current = Thread.currentThread();
        sign .compareAndSet(current, null);
      }
    }

    使用了CAS原子操作,lock函数将owner设置为当前线程,并且预测原来的值为空。unlock函数将owner设置为null,并且预测值为当前线程。 

    当有第二个线程调用lock操作时由于owner值不为空,导致循环一直被执行,直至第一个线程调用unlock函数将owner设置为null,第二个线程才能进入临界区。

    由于自旋锁只是将当前线程不停地执行循环体,不进行线程状态的改变,所以响应速度更快。但当线程数不停增加时,性能下降明显,因为每个线程都需要执行,占用CPU时间。如果线程竞争不激烈,并且保持锁的时间段。适合使用自旋锁。

    注:该例子为非公平锁,获得锁的先后顺序,不会按照进入lock的先后顺序进行。

    偏向锁/轻量级锁/重量级锁

    这三种锁,就是指锁的状态,针对synchronized

    偏向锁是指一段代码一直被一个线程所访问,那么理论上,这个线程会自动获取这个锁,并一直拥有这个锁,这样就降低了获取锁的代价。

    轻量级锁是指当偏向锁的状态下,被另一个线程访问,偏向锁就会升级为轻量级锁,其他线程会通过自旋形式尝试获取锁,不会阻塞,提高效率。

    重量级锁是指在轻量级锁的状态下,另一个线程虽然自旋,但自选不会一直持续下去,当自旋一定次数的时候还没有获取到锁的话,就会进入阻塞,该锁就会膨胀为重量级锁,重量级锁会让其他申请的线程陷入阻塞,降低性能。

  • 相关阅读:
    sql脚本:将一个数据库完整复制到另一个数据库(转)
    问题:DropDownList启用AutoPostback后,SelectedIndexChanged事件跟踪不到
    学习:如何在已有MOSS的环境下重装IIS(转)
    学习:MOSS2007 实现单点登陆(转)
    sql脚本:恢复数据库(根据备份的bak)(转)
    学习:深入浅出之正则表达式(转)
    错误:此网页的安全性验证无效并且可能损坏。请单击 Web 浏览器中的“后退”,刷新网页,再重试操作
    学习:关于代码调用SSP获取UserProfile出错的解决方案(转)
    问题:提升权限后,更新SPListItem即 Item.Update()出错问题
    学习:char、varchar、text和nchar、nvarchar、ntext的区别(转)
  • 原文地址:https://www.cnblogs.com/K-artorias/p/8108557.html
Copyright © 2020-2023  润新知