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

1、Java都有哪些锁?

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

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。

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

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

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

java锁有哪些类(转)的更多相关文章

  1. Java锁之乐观锁、悲观锁、自旋锁

    java锁分为三大类乐观锁.悲观锁.自旋锁 乐观锁:乐观锁是一种乐观思想,即认为读多写少,遇到并发写的可能性低,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别 ...

  2. Java锁Synchronized对象锁和类锁区别

    java的内置锁:每个java对象都可以用做一个实现同步的锁,这些锁成为内置锁.线程进入同步代码块或方法的时候会自动获得该锁,在退出同步代码块或方法时会释放该锁.获得内置锁的唯一途径就是进入这个锁的保 ...

  3. java内置锁实现锁住代码块方案(同一个对象或锁住整个类.class)

    我们看一个例子: class Demo { public synchronized void test() { System.out.println("test方法开始执行,当前线程为:&q ...

  4. java 锁4

    关于锁的分类 及 锁的灵活使用: 参见 http://blog.csdn.net/qaz13177_58_/article/details/21543515  有几句话说得相当不错: 锁的分类 : 同 ...

  5. java 锁!

    问题:如何实现死锁. 关键: 1 两个线程ta.tb 2 两个对象a.b 3 ta拥有a的锁,同时在这个锁定的过程中,需要b的锁:tb拥有b的锁,同时在这个锁定的过程中,需要a的锁: 关键的实现难点是 ...

  6. Java多线程基础——Lock类

    之前已经说道,JVM提供了synchronized关键字来实现对变量的同步访问以及用wait和notify来实现线程间通信.在jdk1.5以后,JAVA提供了Lock类来实现和synchronized ...

  7. JAVA 锁之 Synchronied

    ■ Java 锁 1. 锁的内存语义 锁可以让临界区互斥执行,还可以让释放锁的线程向同一个锁的线程发送消息 锁的释放要遵循 Happens-before 原则(锁规则:解锁必然发生在随后的加锁之前) ...

  8. Java锁机制了解一下

    前言 回顾前面: 多线程三分钟就可以入个门了! Thread源码剖析 多线程基础必要知识点!看了学习多线程事半功倍 只有光头才能变强! 本文章主要讲的是Java多线程加锁机制,有两种: Synchro ...

  9. Java 锁机制 synchronized

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/75126630 本文出自[赵彦军的博客] 1.前言 在多线程并发编程中Synchro ...

随机推荐

  1. 全方面了解和学习PHP框架

    PHP框架是什么?    PHP框架提供了一个用以构建web应用的基本框架,从而简化了用PHP编写web应用程序的流程.这样不但节省开发时间,有助于建立更稳定的应用,而且减少了重复编码的开发.框架还可 ...

  2. Linux系统查找清理磁盘大文件

    本文主要介绍Linux系统磁盘使用空间不足时,如何查找大文件并进行清理的方法. 使用df-h检查一台服务器磁盘使用空间,发现磁盘已经使用了100%,其中/dev/mapper/vg_iavp-lv_r ...

  3. leetcode记录-罗马数字转整数

    罗马数字包含以下七种字符: I, V, X, L,C,D 和 M. 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如, 罗马数字 2 写做 II ,即为两个并 ...

  4. 机器人操作系统ROS-工作空间的建立

    运行例子为重德智能的github中的robot_sim_demo 创建一个robot_ws工作空间 1. mkdir -p robot_ws/src   #创建catkin 工作空间 2. cd ro ...

  5. ASP.NET底层与各个组件的初步认识与理解 (转载)

    ASP.NET底层的初步认识与理解   最近在国外的网站乱走一通,发现一些比较好的文章,收集整理加于自己的理解,作为笔记形式记录下来,让以后自己有个回忆. ASP.NET是一个非常强大的构建Web应用 ...

  6. 20155224 2016-2017-2 《Java程序设计》第4周学习总结

    20155224 2016-2017-2 <Java程序设计>第4周学习总结 教材学习内容总结 第六章 第六章主要学习了子类与父类的继承. 先定义一个程序,另一程序可继承他 如: publ ...

  7. 20155304 2016-2017-2 《Java程序设计》实验五(网络编程与安全)实验报告

    20155304 2016-2017-2 <Java程序设计>实验五(网络编程与安全)实验报告 实验内容及步骤: 一.两人一组结对编程: 参考http://www.cnblogs.com/ ...

  8. OpenStack入门篇(三)之KVM介绍及安装

    1.什么是虚拟化? 虚拟化是云计算的基础.简单的说,虚拟化使得在一台物理的服务器上可以跑多台虚拟机,虚拟机共享物理机的 CPU.内存.IO 硬件资源,但逻辑上虚拟机之间是相互隔离的. 物理机我们一般称 ...

  9. Linux安装gitlab

    一.GitLab 是一个用于仓库管理系统的开源项目,使用Git作为代码管理工具,并在此基础上搭建起来的web服务.安装方法是参考GitLab在GitHub上的Wiki页面. 二.我相信使用过git的开 ...

  10. redis sentinel介绍

    目录 配置redis主从复制 使用ping命令检查是否启动 主节点查看链接信息 开始部署sentinel 节点 部署sentinel 启动sentinel 演示下故障转移 查看当前sentinel监控 ...