java锁有哪些类(转)

摘要:
公平锁/不公平锁可重入锁独占锁/共享锁互斥锁/读/写锁乐观锁/悲观锁分段锁偏置锁/轻量级锁/重量级锁自旋锁Java实现锁有两种语法,一种是synchronized语句,另一种是重入锁关键字。JavaJavarecenteranthlock通过构造函数指定锁是公平的还是不公平的。默认情况下,它是一个非公平锁。对于synchronized,它也是一个不公平的锁。自旋锁在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

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

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

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

免责声明:文章转载自《java锁有哪些类(转)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇BehaviorTree.CPP行为树BT的入门(二)MySQL客户端mysqladmin命令下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

HBase的Write Ahead Log (WAL) —— 整体架构、线程模型

解决的问题 HBase的Write Ahead Log (WAL)提供了一种高并发、持久化的日志保存与回放机制。每一个业务数据的写入操作(PUT / DELETE)执行前,都会记账在WAL中。 如果出现HBase服务器宕机,则可以从WAL中回放执行之前没有完成的操作。 本文主要探讨HBase的WAL机制,如何从线程模型、消息机制的层面上,解决这些问题: 1...

Netty (1)

目录 Netty(1) 传统的阻塞I/O模型(BIO) 特点 问题 事件驱动模型 Netty高效的 Reactor 线程模型 Reactor单线程模型 Reactor多线程模型 Reactor主从多线程模型 Netty特性 多路复用模型 数据零拷贝 无锁化设计 高性能的序列化框架 Netty(1) 官网的介绍,Netty 是...

JVM性能调优监控工具专题一:JVM自带性能调优工具(jps,jstack,jmap,jhat,jstat,hprof)

性能分析工具jstatjmapjhatjstack 前提概要: JDK本身提供了很多方便的JVM性能调优监控工具,除了集成式的VisualVM和jConsole外,还有jps、jstack、jmap、jhat、jstat、hprof等小巧的工具,每一种工具都有其自身的特点,用户可以根据你需要检测的应用或者程序片段的状况,适当的选择相应的工具进行检测。...

IOCP 浅析(java代码实现)

随着计算机技术,尤其是网络技术的飞速发展,如今的程序开发人员不仅仅局限于基于单机运行或单一线程的应用程序的开发。服务器端 / 客户端模式的最显著的特点是一个服务器端应用能同时为多个客户端提供服务。而传统的服务器端 / 客户端模式通常为每一个客户端创建一个独立的线程,这种实现方式在客户端数量不多的情况下问题不大,但对于类似于铁路网络订票这样的瞬间客户数量巨大...

安卓多线程的实现

有以下几种方式: 1)Activity.runOnUiThread(Runnable) 2)View.post(Runnable) ;View.postDelay(Runnable , long) 3)Handler 4)AsyncTask Android是单线程模型,这意味着Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行,所以你...

深度剖析OpenGL ES中的多线程和多窗口渲染技术

由 创新网小编 于 星期五, 2014-04-11 14:56 发表 移动设备中的CPU和GPU已经变得很强大,到处都是配备一个或多个高分辨率屏幕的设备,需要使用带有图形驱动器的复杂交互也日益增加。在这篇博客文章中,我将讨论多线程和多窗口渲染对开发人员来讲意味着什么,同时我将介绍将这些技术应用您设计当中的条件和时机。 什么是多线程渲染? 传统上,Ope...