显示锁(一)Lock显示锁的优点

转载自 Java 并发:Lock 框架详解

摘要:

  我们已经知道,synchronized 是java的关键字,是Java的内置特性,在JVM层面实现了对临界资源的同步互斥访问,但 synchronized 粒度有些大,在处理实际问题时存在诸多局限性,比如响应中断等。Lock 提供了比 synchronized更广泛的锁操作,它能以更优雅的方式处理线程同步问题。本文以synchronized与Lock的对比为切入点,对Java中的Lock框架的枝干部分进行了详细介绍,最后给出了锁的一些相关概念。


一. synchronized 的局限性 与 Lock 的优点

  回顾文章《Java 并发:内置锁 Synchronized》,如果一个代码块被synchronized关键字修饰,当一个线程获取了对应的锁,并执行该代码块时,其他线程便只能一直等待直至占有锁的线程释放锁。事实上,占有锁的线程释放锁一般会是以下三种情况之一:

  • 占有锁的线程执行完了该代码块,然后释放对锁的占有;
  • 占有锁线程执行发生异常,此时JVM会让线程自动释放锁;
  • 占有锁线程进入 WAITING 状态从而释放锁,例如在该线程中调用wait()方法等。

synchronized 是Java语言的内置特性,可以轻松实现对临界资源的同步互斥访问。那么,为什么还会出现Lock呢?试考虑以下三种情况:


Case 1 :
 
在使用synchronized关键字的情形下,假如占有锁的线程由于要等待IO或者其他原因(比如调用sleep方法)被阻塞了,但是又没有释放锁,那么其他线程就只能一直等待,别无他法。这会极大影响程序执行效率。因此,就需要有一种机制可以不让等待的线程一直无期限地等待下去(比如只等待一定的时间 (解决方案:tryLock(long time, TimeUnit unit)) 或者 能够响应中断 (解决方案:lockInterruptibly())),这种情况可以通过 Lock 解决。

Case 2 :
 
我们知道,当多个线程读写文件时,读操作和写操作会发生冲突现象,写操作和写操作也会发生冲突现象,但是读操作和读操作不会发生冲突现象。但是如果采用synchronized关键字实现同步的话,就会导致一个问题,即当多个线程都只是进行读操作时,也只有一个线程在可以进行读操作,其他线程只能等待锁的释放而无法进行读操作。因此,需要一种机制来使得当多个线程都只是进行读操作时,线程之间不会发生冲突。同样地,Lock也可以解决这种情况 (解决方案:ReentrantReadWriteLock)

Case 3 :
 
我们可以通过Lock得知线程有没有成功获取到锁 (解决方案:ReentrantLock) ,但这个是synchronized无法办到的。


  上面提到的三种情形,我们都可以通过Lock来解决,但 synchronized 关键字却无能为力。事实上,Lock 是 java.util.concurrent.locks包 下的接口,Lock 实现提供了比 synchronized 关键字 更灵活、更广泛、粒度更细 的锁操作,它能以更优雅的方式处理线程同步问题。也就是说,Lock提供了比synchronized更多的功能。但是要注意以下几点:

  1) synchronized是Java的关键字,因此是Java的内置特性,是基于JVM层面实现的,其经过编译之后,会在同步块的前后分别形成 monitorenter 和 monitorexit 两个字节码指令;而Lock是一个Java接口,是基于JDK层面实现的,通过这个接口可以实现同步访问;

  2) 采用synchronized方式不需要用户去手动释放锁,当synchronized方法或者synchronized代码块执行完之后,系统会自动让线程释放对锁的占用;而 Lock则必须要用户去手动释放锁 (发生异常时,不会自动释放锁)如果没有主动释放锁,就有可能导致死锁现象。

  这是很好理解的。Synchronized方式是Java原生支持的,开发人员在使用它来解决并发问题时,一定会方便很多,在这里,开发人员就不需要手动获取锁和释放锁,这些操作均有Java自身自动完成;而Lock方式是JDK层面的提供给开发人员的接口,因此开发人员在使用它来解决并发问题时,需要手动获取锁和释放锁。



最后注意一下:

synchronized是内置在JVM中的,所以它在以后的获得性能提升将会更加直接。所以在没有使用到Lock的高级功能,尽可能地使用 synchronized。

原文地址:https://www.cnblogs.com/jinggod/p/8491109.html

时间: 2024-09-29 21:26:31

显示锁(一)Lock显示锁的优点的相关文章

锁屏上显示Activity

在Android中,有些比较强的提醒,需要用户紧急处理的内容.需要唤醒屏幕,甚至在锁定屏幕的情况下,也要显示出来.例如,来电界面和闹钟提醒界面.这是怎样实现的呢? 其实,实现起来非常简单.只要给Activity的Window添加如下属性即可: @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().addFlags(WindowMa

13 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件  queue队列 生产者消费者模型 Queue队列 开发一个线程池

本节内容 操作系统发展史介绍 进程.与线程区别 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生产者消费者模型 Queue队列 开发一个线程池 进程 语法 进程间通讯 进程池 操作系统发展史 手工操作(无操作系统) 1946年第一台计算机诞生--20世纪50年代中期,还未出现操作系统,计算机工作采用手工操作方式. 手工操作程序员将对应于程序和数据的已穿孔的纸带(或卡片)装入输入机,然后启动输入机把

同步锁(lock)

有两种机制防止代码块受并发访问的干扰: 1.一个是使用synchronized关键字. 2.使用ReentrantLock类.(通过显示定义同步锁对象来实现同步.) 同步锁(lock)方法是控制多个线程对共享资源进行访问的工具.通常,锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象加锁,线程开始访问共享资源之前先获得Lock对象. Lock.ReadWriteLock(读写锁)是java 5 提供的两个根接口.别为Lock接口提供了ReentrantLock(可重入锁)实现类:为R

JUC--Callable 以及Lock同步锁

/** * 一.创建执行线程的方式三:实现Callable接口.相较于实现Runnable接口方式,方法可以有返回值,并且可以抛出异常 * 二.callable 需要FutureTask实现类的支持.用于接受运算结果.FutureTask是Future接口的实现类. * * 线程执行完之后才会执行result.get 可以当做闭锁看 */ public class TestCallable { public static void main(String[] args) { ThreadDemo

mysql被锁住 Lock wait timeout exceeded; try restarting transaction

解决方案1 在mysql中数据库information_schema中查询下面三张表 select * from innodb_trx; ## 当前运行的所有事务 select * from innodb_locks; ## 当前出现的锁 select * from innodb_lock_waits; ## 锁等待的对应关系 在innodb_trx中找到被锁线程的id,kill掉 kill xxxx ------------------------- 命令show processlist详解

[C#基础]说说lock到底锁谁?

写在前面 最近一个月一直在弄文件传输组件,其中用到多线程的技术,但有的地方确实需要只能有一个线程来操作,如何才能保证只有一个线程呢?首先想到的就是锁的概念,最近在我们项目组中听的最多的也是锁谁,如何锁?看到有同事使用lock(this),也有lock(private static object),那就有点困惑了,lock到底锁谁才是最合适的呢? lock 首先先上官方Msdn的说法 lock 关键字可确保当一个线程位于代码的临界区时,另一个线程不会进入该临界区. 如果其他线程尝试进入锁定的代码,

锁对象Lock

Lock 实现提供了比使用synchronized 方法和语句可获得的更广泛的锁定操作,它能以更优雅的方式处理线程同步问题: public class LockTest { publicstaticvoid main(String[] args) { final Outputter1 output = new Outputter1(); new Thread() { publicvoid run() { output.output("zhangsan"); }; }.start();

Java 线程锁机制 -Synchronized Lock 互斥锁 读写锁

synchronized 是互斥锁: lock 更广泛,包含了读写锁 读写锁特点: 1)多个读者可以同时进行读2)写者必须互斥(只允许一个写者写,也不能读者写者同时进行)3)写者优先于读者(一旦有写者,则后续读者必须等待,唤醒时优先考虑写者) 互斥锁特点: 一次只能一个线程拥有互斥锁,其他线程只有等待 所谓互斥锁, 指的是一次最多只能有一个线程持有的锁. 在jdk1.5之前, 我们通常使用synchronized机制控制多个线程对共享资源的访问. 而现在, Lock提供了比synchronize

列出对象锁(lock)信息及其被杀的会话(sid,serial#)信息

check_lock.sql脚本  列出对象锁(lock)信息及其被杀的会话(sid,serial#)信息 set linesize 132 pagesize 66  break on Kill on username on terminal  column Kill heading 'Kill String' format a13  column res heading 'Resource Type' format 999  column id1 format 9999990  column