文档章节

线程锁,Lock,(ReentrantLock与synchronized)

满风
 满风
发布于 2016/04/15 10:28
字数 1460
阅读 365
收藏 6


关于互斥锁:

所谓互斥锁, 指的是一次最多只能有一个线程持有的锁. 在jdk1.5之前, 我们通常使用synchronized机制控制多个线程对共享资源的访问. 而现在, Lock提供了比synchronized机制更广泛的锁定操作, Lock和synchronized机制的主要区别:

synchronized机制提供了对与每个对象相关的隐式监视器锁的访问, 并强制所有锁获取和释放均要出现在一个块结构中, 当获取了多个锁时, 它们必须以相反的顺序释放. synchronized机制对锁的释放是隐式的, 只要线程运行的代码超出了synchronized语句块范围, 锁就会被释放. 

但有时也需要以更为灵活的方式使用锁,比如说在并发编程中有时候,有时候允许以任何顺序获取和释放多个锁,从而支持使用Lock。

而Lock机制必须显式的调用Lock对象的unlock()方法才能释放锁, 这为获取锁和释放锁不出现在同一个块结构中, 以及以更自由的顺序释放锁提供了可能. 

一:synchronized的两种用法

1.内部锁

Java 提供了原子性的内置锁机制: sychronized 块。它包含两个部分:锁对象的引用和这个锁保护的代码块:


synchronized(lock) {
 // 访问或修改被锁保护的共享状态
}



内部锁扮演了互斥锁( mutual exclusion lock, 也称作 mutex )的角色,一个线程拥有锁的时候,别的线程阻塞等待。

2.重进入

指的是同一个线程多次试图获取它所占有的锁,请求会成功。当释放锁的时候,直到重入次数清零,锁才释放完毕

Public class Widget {
      Public synchronized void doSomething(){
           …
      }
}
Public class LoggingWidget extends Widget {
   Public synchronized void doSomething(){
      System.out.println(toString()+”:calling doSomething”);
      Super.doSomething();
   }
}



一般来说,在多线程程序中,某个任务在持有某对象的锁后才能运行任务,其他任务只有在该任务释放同一对象锁后才能拥有对象锁,然后执行任务。于是,想到,同一个任务在持有同一个对象的锁后,在不释放锁的情况下,继续调用同一个对象的其他同步(synchronized)方法,该任务是否会再次持有该对象锁呢? 

    答案是肯定的。

同一个任务在调用同一个对象上的其他synchronized方法,可以再次获得该对象锁

synchronized  m1(){  
//加入此时对锁a的计数是N  
 m2();  //进入m2的方法体之后锁计数是N+1,离开m2后是N  
}  
synchronized m2(){}


二:ReentrantLock 实现了Lock

一个可重入的互斥锁 Lock,它具有与使用 synchronized 方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大。

public interface Lock
Lock  实现提供了比使用  synchronized  方法和语句可获得的更广泛的锁定操作。此实现允许更灵活的结构,可以具有差别很大的属性,可以支持多个相关的  Condition  对象

ReentrantLock 将由最近成功获得锁,并且还没有释放该锁的线程所拥有。当锁没有被另一个线程所拥有时,调用 lock 的线程将成功获取该锁并返回。如果当前线程已经拥有该锁,此方法将立即返回。可以使用 isHeldByCurrentThread() 和 getHoldCount() 方法来检查此情况是否发生。

此类的构造方法接受一个可选的公平 参数。当设置为 true 时,在多个线程的争用下,这些锁倾向于将访问权授予等待时间最长的线程。否则此锁将无法保证任何特定访问顺序。与采用默认设置(使用不公平锁)相比,使用公平锁的程序在许多线程访问时表现为很低的总体吞吐量(即速度很慢,常常极其慢),但是在获得锁和保证锁分配的均衡性时差异较小。不过要注意的是,公平锁不能保证线程调度的公平性。因此,使用公平锁的众多线程中的一员可能获得多倍的成功机会,这种情况发生在其他活动线程没有被处理并且目前并未持有锁时。还要注意的是,未定时的 tryLock 方法并没有使用公平设置。因为即使其他线程正在等待,只要该锁是可用的,此方法就可以获得成功。

建议总是 立即实践,使用 lock 块来调用 try,在之前/之后的构造中,最典型的代码如下:
class X {
   private final ReentrantLock lock = new ReentrantLock();
   // ...

   public void m() { 
     lock.lock();  // block until condition holds
     try {
       // ... method body
     } finally {
       lock.unlock()
     }
   }
 }


ReentrantLock 的lock机制有2种,忽略中断锁和响应中断锁,这给我们带来了很大的灵活性。

比如:如果A、B 2个线程去竞争锁,A线程得到了锁,B线程等待,但是A线程这个时候实在有太多事情要处理,就是 一直不返回,B线程可能就会等不及了,想中断自己,不再等待这个锁了,转而处理其他事情。这个时候ReentrantLock就提供了2种机制,

第一,B线程中断自己(或者别的线程中断它),但是ReentrantLock 不去响应,继续让B线程等待,你再怎么中断,我全当耳边风(synchronized原语就是如此);

第二,B线程中断自己(或者别的线程中断它),ReentrantLock 处理了这个中断,并且不再等待这个锁的到来,完全放弃。

代码:  
lock.lockInterruptibly();// 注意这里,可以响应中断



© 著作权归作者所有

共有 人打赏支持
满风

满风

粉丝 84
博文 166
码字总数 175990
作品 0
杭州
技术主管
ReentrantLock与Synchronized

ReentrantLock和synchronized两种锁定机制 ReentrantLock和synchronized两种锁定机制 1.应用synchronized同步锁 把代码块声明为 synchronized,使得该代码具有 原子性(atomicity)和 可见性...

J星星点灯
2017/09/09
0
0
ReentrantLock与synchronized

关于互斥锁: 所谓互斥锁, 指的是一次最多只能有一个线程持有的锁. 在jdk1.5之前, 我们通常使用synchronized机制控制多个线程对共享资源的访问. 而现在, Lock提供了比synchronized机制更广泛...

梁金晶
2016/09/29
3
0
Java并发编程 - 显示锁Lock和ReentrantLock

Lock Lock是一个接口,提供了无条件的、可轮询的、定时的、可中断的锁获取操作,所有加锁和解锁的方法都是显式的。包路径是:。核心方法有 ,,,实现类有 、、。 方法及说明 ReentrantLock ...

bobjoy
2016/12/21
14
0
深入理解ReentrantLock

在Java中通常实现锁有两种方式,一种是synchronized关键字,另一种是Lock。二者其实并没有什么必然联系,但是各有各的特点,在使用中可以进行取舍的使用。首先我们先对比下两者。 实现: 首先...

孟飞阳
2016/07/25
33
0
深入研究 Java Synchronize 和 Lock 的区别与用法

在分布式开发中,锁是线程控制的重要途径。Java为此也提供了2种锁机制,synchronized和lock。做为Java爱好者,自然少不了对比一下这2种机制,也能从中学到些分布式开发需要注意的地方。 我们...

again-Y
2013/10/23
0
5

没有更多内容

加载失败,请刷新页面

加载更多

linux使用ntfs-3g操作ntfs格式硬盘

Linux内核目前只支持对微软NTFS文件系统的读取。 NTFS-3G 是微软 NTFS 文件系统的一个开源实现,同时支持读和写。NTFS-3G 开发者使用 FUSE 文件系统来辅助开发,同时对可移植性有益。 安装 ...

linuxprobe16
今天
1
0
kubeadm部署kubernetes集群

一、环境要求 这里使用RHEL7.5 master、etcd:192.168.10.101,主机名:master node1:192.168.10.103,主机名:node1 node2:192.168.10.104,主机名:node2 所有机子能基于主机名通信,编辑...

人在艹木中
今天
10
0
Shell特殊符号总结以及cut,sort,wc,uniq,tee,tr,split命令

特殊符号总结一 * 任意个任意字符 ? 任意一个字符 # 注释字符 \ 脱义字符 | 管道符 # #号后的备注被忽略[root@centos01 ~]# ls a.txt # 备注 a.txt[root@centos01 ~]# a=1[root@centos01...

野雪球
今天
3
0
OSChina 周二乱弹 —— 程序员圣衣

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @达尔文:分享Skeeter Davis的单曲《The End of the World》 《The End of the World》- Skeeter Davis 手机党少年们想听歌,请使劲儿戳(这里...

小小编辑
今天
20
2
[ python import module ] 导入模块

import moudle_name ----> import module_name.py ---> import module_name.py文件路径 -----> sys.path (这里进行查找文件) # from app.web import Personimport app.web.Person as Pe......

_______-
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部