import java.util.concurrent.locks.ReentrantLock;

/**
* 重入锁 ReenterLock 一个线程允许连续获得同一把锁,注意:必须释放相同次数,释放次数多,会异常,少了相当于线程还持有这个锁,其他线程无法进入临界区
* 需要手动指定何时加锁何时释放锁
*
ReenterLock几个重要方法:
- lock():获得锁,如果锁已经被占用,则等待
- lockInterruptibly():获得锁,但优先响应中断
- tryLock():尝试获得锁,成功返回true,失败返回false,该方法不等待,立即返回
- tryLock(long time,TimeUnit unit):在给定时间内尝试获得锁
- unlock():释放锁
*/
public class ReentrantLockDemo implements Runnable{
public static Integer i = 0;
public static ReentrantLock lock = new ReentrantLock(); @Override
public void run() {
for (int j = 0; j < 10000000; j++) {
lock.lock();
try {
i++;
}finally {
lock.unlock();
}
}
}
public static void main(String[] args) throws InterruptedException{
ReentrantLockDemo r = new ReentrantLockDemo();
Thread thread1 = new Thread(r);
Thread thread2 = new Thread(r);
thread1.start();thread2.start();
thread1.join();thread2.join();
System.out.println(i);//20000000
}
}

中断处理

import java.util.concurrent.locks.ReentrantLock;

/**
* 避免死锁
* 重入锁的中断处理能力
*/
public class IntLock implements Runnable{
public static ReentrantLock lock1 = new ReentrantLock();
public static ReentrantLock lock2 = new ReentrantLock();
int lock;
public IntLock(int lock) {
this.lock = lock;
}
@Override
public void run() {
try {
if (lock==1){
lock1.lockInterruptibly();
Thread.sleep(500);
lock2.lockInterruptibly();//可以对中断进行响应的锁
}else {
lock2.lockInterruptibly();
Thread.sleep(500);
lock1.lockInterruptibly(); //22行
}
}catch (InterruptedException e){
e.printStackTrace();
}finally {
//检查当前线程是否拥有该锁
if (lock1.isHeldByCurrentThread()) lock1.unlock();
if (lock2.isHeldByCurrentThread()) lock2.unlock();
System.out.println(Thread.currentThread().getId()+":线程退出");
}
}
public static void main(String[] args) throws InterruptedException{
IntLock i1 = new IntLock(1);
IntLock i2 = new IntLock(2);
Thread t1 = new Thread(i1);
Thread t2 = new Thread(i2);
t1.start();
t2.start();
Thread.sleep(1000);
t2.interrupt(); //中断t2 ,t2放弃对lock1的申请,同时释放已获得的lock2
//java.lang.InterruptedException
// at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:898)
// at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222)
// at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
// at com.combat.IntLock.run(IntLock.java:22)
// at java.lang.Thread.run(Thread.java:748)
//10:线程退出
//9:线程退出
}
}

限时等待

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock; /**
* 限时等待锁
*/
public class TimeLockDemo implements Runnable{
public static ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
try {
if (lock.tryLock(5, TimeUnit.SECONDS)){ //等待时间,计时单位
Thread.sleep(6000);
}else {
System.out.println("get lock failed");
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (lock.isHeldByCurrentThread())lock.unlock();
}
}
public static void main(String[] args){
TimeLockDemo demo = new TimeLockDemo();
Thread t1 = new Thread(demo);
Thread t2 = new Thread(demo);
t1.start();
t2.start();
}
//get lock failed
//由于占用锁的线程为6秒,另一个线程无法在5秒的等待时间内获得锁,因此请求锁失败
}
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock; /**
* tryLock
* 限时等待锁 无参数 如果锁被其他线程占用,则当前线程不会进行等待,而是立即返回false,不会引起线程等待
*/
public class TimeLockDemo2 implements Runnable{
public static ReentrantLock lock1 = new ReentrantLock();
public static ReentrantLock lock2 = new ReentrantLock();
int lock;
public TimeLockDemo2(int lock) {
this.lock = lock;
}
@Override
public void run() {
if (lock == 1){
while (true){
if (lock1.tryLock()){
try {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (lock2.tryLock()){
try {
System.out.println(Thread.currentThread().getId()+":my job done");
return;
} finally {
lock2.unlock();
}
}
} finally {
lock1.unlock();
}
}
}
}else {
while (true){
if (lock2.tryLock()){
try {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (lock1.tryLock()){
try {
System.out.println(Thread.currentThread().getId()+":my job done");
return;
} finally {
lock1.unlock();
}
}
} finally {
lock2.unlock();
}
}
}
}
}
public static void main(String[] args){
TimeLockDemo2 r1 = new TimeLockDemo2(1);
TimeLockDemo2 r2 = new TimeLockDemo2(1);
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
}
//9:my job done
//10:my job done
}

公平锁

import java.util.concurrent.locks.ReentrantLock;

/**
* 公平锁
* synchronized产生的锁是非公平锁
* 重入锁可以设置公平性
*/
public class FairLock implements Runnable{
public static ReentrantLock lock = new ReentrantLock(true);
@Override
public void run() {
while (true){
try {
lock.lock();
System.out.println(Thread.currentThread().getName()+"获得锁");
} finally {
lock.unlock();
}
}
}
public static void main(String[] args) throws InterruptedException{
FairLock lock = new FairLock();
Thread t1 = new Thread(lock, "thread_t1");
Thread t2 = new Thread(lock, "thread_t2");
t1.start();
t2.start();
}
//...
//thread_t2获得锁
//thread_t1获得锁
//thread_t2获得锁
//thread_t1获得锁
//thread_t2获得锁
//...
//两个线程基本交替获得锁 //而非公平锁,一个线程会倾向于再次获得已持有的锁,这种分配方式是高效的,但无公平性可言
}

20.ReenterLock重入锁的更多相关文章

  1. AQS学习(二) AQS互斥模式与ReenterLock可重入锁原理解析

    1. MyAQS介绍    在这个系列博客中,我们会参考着jdk的AbstractQueuedLongSynchronizer,从零开始自己动手实现一个AQS(MyAQS).通过模仿,自己造轮子来学习 ...

  2. 可重入锁(good)

    可重入锁,也叫做递归锁,是指在一个线程中可以多次获取同一把锁,比如:一个线程在执行一个带锁的方法,该方法中又调用了另一个需要相同锁的方法,则该线程可以直接执行调用的方法[即可重入],而无需重新获得锁: ...

  3. Java多线程——深入重入锁ReentrantLock

    简述 ReentrantLock 是一个可重入的互斥(/独占)锁,又称为“独占锁”. ReentrantLock通过自定义队列同步器(AQS-AbstractQueuedSychronized,是实现 ...

  4. 浅谈Java中的锁:Synchronized、重入锁、读写锁

    Java开发必须要掌握的知识点就包括如何使用锁在多线程的环境下控制对资源的访问限制 ◆ Synchronized ◆ 首先我们来看一段简单的代码: 12345678910111213141516171 ...

  5. synchronized 是可重入锁吗?为什么?

    什么是可重入锁? 关于什么是可重入锁,我们先来看一段维基百科的定义. 若一个程序或子程序可以“在任意时刻被中断然后操作系统调度执行另外一段代码,这段代码又调用了该子程序不会出错”,则称其为可重入(re ...

  6. JAVA锁机制-可重入锁,可中断锁,公平锁,读写锁,自旋锁,

    如果需要查看具体的synchronized和lock的实现原理,请参考:解决多线程安全问题-无非两个方法synchronized和lock 具体原理(百度) 在并发编程中,经常遇到多个线程访问同一个 ...

  7. Java多线程系列——深入重入锁ReentrantLock

    简述 ReentrantLock 是一个可重入的互斥(/独占)锁,又称为“独占锁”. ReentrantLock通过自定义队列同步器(AQS-AbstractQueuedSychronized,是实现 ...

  8. synchronized的功能拓展:重入锁(读书笔记)

     重入锁可以完全代替synchronized关键字.在JDK5.0的早期版本中,重入锁的性能远远好于synchronized,但是从JDK6.0开始.JDK在synchronized上做了大量的优化. ...

  9. redis实现分布式锁需要考虑的因素以及可重入锁实现

    死锁 错误例子 解决方式  防止死锁 通过设置超时时间  不要使用setnx key   expire 20  不能保证原子性 如果setnx程序就挂了 没有执行expire就死锁了  reidis2 ...

随机推荐

  1. AI比医生更好地发现皮肤癌,未来计算机技术可渗透医院

    未来机器人将取代医生?这可能是事实.为什么这么多年轻人选择计算机行业,因为这是一个趋势.据法新社报道,研究人员周二称,一项计算机技术比人类皮肤科医生在检测皮肤癌方面的表现要好得多,因为这项研究是为了寻 ...

  2. 学习加密(四)spring boot 使用RSA+AES混合加密,前后端传递参数加解密

      学习加密(四)spring boot 使用RSA+AES混合加密,前后端传递参数加解密 技术标签: RSA  AES  RSA AES  混合加密  整合   前言:   为了提高安全性采用了RS ...

  3. vue部署后刷新404问题

    为什么会404NotFound Internet Information Services (IIS) 第一步:安装 IIS UrlRewrite 第二步:配置重写URL规则 在你的网站根目录中创建一 ...

  4. SpringBoot JSON文件读取

    @Componentpublic class StepExecutor implements Runnable { @Value("classpath:menu.json") pr ...

  5. 状压 DP:[USACO06NOV] Corn Fields,[USACO13NOV] No Change

    [USACO06NOV] Corn Fields (试题来源:Link ) 题目描述 Farmer John has purchased a lush new rectangular pasture ...

  6. bzoj 1233: [Usaco2009Open]干草堆tower 【想法题】

    首先这题的$n^3$的DP是比较好想的 $f[i][j]$表示用前$i$包干草 且最顶层为第$j+1$包到第$i$包 所能达到的最大高度 然而数据范围还是太大了 因此我们需要去想一想有没有什么单调性 ...

  7. (60)c# com com+ dcom

    一.创建COM组件 1.创建项目 2.设置使程序集可见 AssemblyInfo.cs中flase改为ture 或者 项目属性 设置可见 3.Guid生成器 在开始程序下能够找到Guid生成器 每次都 ...

  8. Python多进程编程-进程间协作(Queue、Lock、Semaphore、Event、Pipe)

    进程与进程之间是相互独立的,互不干扰.如果多进程之间需要对同一资源操作,就需要进程间共享变量,上一篇文章介绍了进程间共享数据的三大类Value.Array.Manager,这三种类的主要区别在于管理的 ...

  9. python3反转列表的三种方式

    1.内建函数 reversed() li = [1,2,3,4,5,6] a = list(reversed(li)) print(a) 注意:reversed()函数返回的是一个迭代器,而不是一个L ...

  10. SSDT and Shadow SSDT table

    参考:http://x86.renejeschke.de/html/file_module_x86_id_313.html http://msdn.microsoft.com/en-us/librar ...