`
uptake
  • 浏览: 21036 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java 高并发 ReentrantLock -- 可重入的锁

阅读更多
ReentrantLock -- 可重入的锁
可重入锁指在同一个线程中,可以重入的锁。当然,当这个线程获得锁后,其他线程将等待这个锁被释放后,才可以获得这个锁。
构造器:ReentrantLock(boolean fair): 布尔值用来表示,创建的这个锁是公平的锁,还是自由竞争的锁。所谓公平的锁,是指,各个希望获得所得线程获得锁的顺序是按到达的顺序获得,还是自由竞争获得。
通常的使用方法:
ReentrantLock lock = new ReentrantLock(); // not a fair lock
lock.lock();

try {

    // synchronized do something

} finally {
    lock.unlock();
}
一个典型的例子:先测试可重入锁的重入特性,然后创建3个线程,每个线程启动后,尝试获取锁,获取锁后对共享数据 + 1,然后显示chula

import java.util.Calendar;
import java.util.concurrent.locks.ReentrantLock;
public class TestLock {
private ReentrantLock lock = null;
// 用于线程同步访问的共享数据
public int data = 100;

public TestLock() {
  // 创建一个自由竞争的可重入锁
  lock = new ReentrantLock();
}

public static void main(String[] args) {
 
  TestLock tester = new TestLock();
 
  // 测试可重入,函数testReentry() 执行获取锁后,显示信息的功能
  tester.testReentry();
  // 能执行到这里而不阻塞,表示锁可重入
  tester.testReentry();
  // 再次重入
  tester.testReentry();

  // 释放重入测试的锁,要按重入的数量解锁,否则其他线程无法获取该锁。
  tester.getLock().unlock();
  tester.getLock().unlock();
  tester.getLock().unlock();
 
  // 启动3个线程测试在锁保护下的共享数据data的访问
  tester.test();
}

public ReentrantLock getLock() {
  return lock;
}

public void test() {
  new Thread(new workerThread(this)).start();
  new Thread(new workerThread(this)).start();
  new Thread(new workerThread(this)).start();
}

public void testReentry() {
  lock.lock();
 
  Calendar now = Calendar.getInstance();
 
  System.out.println(now.getTime() + " " + Thread.currentThread() + " get lock.");
}

// 线程调用的方法
public void testRun() throws Exception {
  // 加锁
  lock.lock();
 
  Calendar now = Calendar.getInstance();
  try {
   // 获取锁后显示 当前时间 当前调用线程 共享数据的值(并使共享数据 + 1)
   System.out.println(now.getTime() + " " + Thread.currentThread() + " accesses the data " + data ++);
  
   // 模拟其他处理,这里假设休眠一下
   Thread.sleep(500);
  
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   // 解锁
   lock.unlock();
  }
}
}

// 工作线程,调用TestServer.testRun
class workerThread implements Runnable {

private TestLock tester = null;

public workerThread(TestLock testLock) {
  this.tester = testLock;
}

public void run() {
  // 循环调用,尝试加锁,并对共享数据+1,然后显示出来
  while (true) {
   try {
     // 调用tester.testRun()
     tester.testRun();
   } catch (Exception e) {
    e.printStackTrace();
   }
  }
}
}

程序运行结果:
Tue Jan 24 13:41:45 CST 2006 Thread[main,5,main] get lock.
Tue Jan 24 13:41:46 CST 2006 Thread[main,5,main] get lock.
Tue Jan 24 13:41:46 CST 2006 Thread[main,5,main] get lock.
Tue Jan 24 13:41:46 CST 2006 Thread[Thread-0,5,main] accesses the data 100
Tue Jan 24 13:41:46 CST 2006 Thread[Thread-1,5,main] accesses the data 101
Tue Jan 24 13:41:47 CST 2006 Thread[Thread-2,5,main] accesses the data 102
Tue Jan 24 13:41:47 CST 2006 Thread[Thread-2,5,main] accesses the data 103
Tue Jan 24 13:41:48 CST 2006 Thread[Thread-2,5,main] accesses the data 104
Tue Jan 24 13:41:48 CST 2006 Thread[Thread-0,5,main] accesses the data 105
Tue Jan 24 13:41:49 CST 2006 Thread[Thread-0,5,main] accesses the data 106
Tue Jan 24 13:41:49 CST 2006 Thread[Thread-0,5,main] accesses the data 107
Tue Jan 24 13:41:50 CST 2006 Thread[Thread-0,5,main] accesses the data 108
Tue Jan 24 13:41:50 CST 2006 Thread[Thread-1,5,main] accesses the data 109
Tue Jan 24 13:41:51 CST 2006 Thread[Thread-1,5,main] accesses the data 110

前三行表示main线程,重入3次获得该锁。
第四行表示Thread-0线程,先获得锁,使共享数据+1,然后显示信息,然后释放锁。
第五行表示Thread-1线程,获得锁,使共享数据+1,然后显示信息,然后释放锁。

由程序输出的信息可以知道,各线程获得锁的顺序,是自由竞争的结果。
如果将 lock = new ReentrantLock(); 改为:lock = new ReentrantLock(true);
将看到如下的结果:
Tue Jan 24 13:47:29 CST 2006 Thread[main,5,main] get lock.
Tue Jan 24 13:47:30 CST 2006 Thread[main,5,main] get lock.
Tue Jan 24 13:47:30 CST 2006 Thread[main,5,main] get lock.
Tue Jan 24 13:47:30 CST 2006 Thread[Thread-0,5,main] accesses the data 100
Tue Jan 24 13:47:30 CST 2006 Thread[Thread-1,5,main] accesses the data 101
Tue Jan 24 13:47:31 CST 2006 Thread[Thread-2,5,main] accesses the data 102
Tue Jan 24 13:47:31 CST 2006 Thread[Thread-0,5,main] accesses the data 103
Tue Jan 24 13:47:32 CST 2006 Thread[Thread-1,5,main] accesses the data 104
Tue Jan 24 13:47:32 CST 2006 Thread[Thread-2,5,main] accesses the data 105
Tue Jan 24 13:47:33 CST 2006 Thread[Thread-0,5,main] accesses the data 106
Tue Jan 24 13:47:33 CST 2006 Thread[Thread-1,5,main] accesses the data 107
Tue Jan 24 13:47:34 CST 2006 Thread[Thread-2,5,main] accesses the data 108
Tue Jan 24 13:47:34 CST 2006 Thread[Thread-0,5,main] accesses the data 109
Tue Jan 24 13:47:35 CST 2006 Thread[Thread-1,5,main] accesses the data 110
可以看到各线程获得锁的顺序,是按线程获得锁的顺序。
(注: new Thread(new workerThread()).start(); 并不是表示线程启动的顺序,就是线程获得锁的顺序)java 高并发 ReentrantLock -- 可重入的锁
分享到:
评论

相关推荐

    2023年最新Java高并发多线程面试题

    内容概要:最新2023年Java高并发多线程后端面试题整理, 包含线程池,并发集合,volatile,CountDownLatch,Semaphore,Phaser,AQS,ReentrantLock,ReentrantLock等等问题, 用简洁明了的语言,通俗易懂地阐述了高...

    java高并发相关知识点.docx

    Java高并发相关知识点包括: 线程:Java多线程的实现方式,包括继承Thread类和实现Runnable接口。 锁:Java中的锁机制,包括synchronized关键字和ReentrantLock类。 线程池:Java中的线程池机制,包括线程池的创建...

    汪文君高并发编程实战视频资源下载.txt

     Java高并发第三阶段(JUC).png  高并发编程第三阶段01讲 AtomicInteger多线程下测试讲解.mkv  高并发编程第三阶段02讲 AtomicInteger API详解,以及CAS算法详细介绍.mkv  高并发编程第三阶段03讲 利用CAS构造一...

    JavaHub:Java程序员学习之路,持续更新原创内容,欢迎Star

    我会根据下图中的技能点持续更新原创内容,技能列举的可能不是很完善,朋友们可以去【公众号】或【微信】给我提意见!都到这了,点个【Star】防走丢哦!...高并发编程-ReentrantLock非公平锁深入解析 高并发编程-Reent

    高并发多线程面试专题及答案(上).pdf

    高并发多线程面试专题及答案(上) 包括:Synchronized相关问题 可重入锁ReentrantLock及其他显式锁相关问题 Java线程池相关问题 Java内存模型相关问题

    汪文君高并发编程实战视频资源全集

     Java高并发第三阶段(JUC).png  高并发编程第三阶段01讲 AtomicInteger多线程下测试讲解.mkv  高并发编程第三阶段02讲 AtomicInteger API详解,以及CAS算法详细介绍.mkv  高并发编程第三阶段03讲 利用CAS构造一...

    Java并发编程实战

    如何识别可并行执行的任务,如何提高单线程子系统的响应性,如何确保并发程序执行预期任务,如何提高并发代码的性能和可伸缩性等内容,最后介绍了一些高级主题,如显式锁、原子变量、非阻塞算法以及如何开发自定义的...

    Java并发编程基础.pdf

    线程同步与通信:掌握Java中的同步机制,如synchronized关键字、wait()和notify()方法,以及更高级的并发工具如ReentrantLock、Condition等。了解线程间的通信方式,如共享内存、消息传递等。 并发集合:熟悉Java...

    Java并发包讲解

    3.hashMap , treeMap -- ConcurrentHashMap,ConcurentSkipListMap(key有序,支持更高并发) ## Concurrent同步工具类 countDownLatch CyclicBarrier Semaphore Exchanger ReenTrantLock ...

    高级开发并发面试题和答案.pdf

    ReentrantLock如何实现可重入性 volatile作用; wait 与 sleep 的有什么不同?回答的要点四个: Thread.sleep()和LockSupport.park()的区别 Object.wait()和LockSupport.park()的区别 线程和线程池 线程池的五种状态...

    javaforkjoin源码-gitbook-BAT-interview:本文综合自己在一线互联网工作感悟,经验。记录开源框架的源码解读,数据

    [乐观锁&悲观锁,重入锁&非重入锁,公平锁&非公平锁,锁粒度] [ReentrantLock, ReentrantReadWriteLock, ReadWriteLock源码] [Condition 条件队列和Object.wait队列] 并发同步工具类 [CountDownLatch] ...

    7、深入理解AQS独占锁之ReentrantLock源码分析(1).pdf

    7、深入理解 AQS 独占锁之 Reentrantlock 源码分析 (1).pdf 8、读写锁ReentrantReadWriteLock&StampLock详解.pdf 9、并发容器 (Map、List、Set) 实战及其原理.pdf 10、阻塞队列BlockingQueue 实战及其原理分析.pdf

    高级java笔试题-ShiftJava:学到头秃的Java的小笔记

    并发:线程基础、JMM、AQS、CAS、锁与线程安全(Synchronized、ReentrantLock)、JUC、线程池、定时任务、TreadLocal 等。 4. Java8/IO/其他 Java8:Lambda、流 Stream 等。 IO:文件操作、IO流、网络操作等(NIO 放...

    Lock接口与synchronized关键字

    其次,从功能特性上来看,synchronized具有可重入性,即同一个线程可以多次获取同一个对象的锁,而不会导致死锁。而Lock接口也提供了可重入锁的实现。此外,Lock接口还提供了更灵活的锁获取方式,如可以尝试获取锁...

    java8源码-JUC:日常使用进程/线程的案例或者case

    java.util.concurrent(并发) ##概念复习 进程:正在进行中的程序 线程:进程当中的一个执行单元 关系: 进程包含线程 面试问题: 日常使用进程/线程的案例或者case ###线程的各种状态: Thread.state --枚举 (需手写记忆)...

    Lock锁的底层原理完整版

    Lock锁的灵活性相比synchronized更高,它支持手动获取和释放锁,能够中断的获取锁以及超时获取锁。 具体来说,Lock锁有以下主要方法:lock()用于上锁,unlock()用于解锁,tryLock()尝试非阻塞地获取锁,tryLock...

    基于redis实现分布式锁的原理与方法

    为了保证一个在高并发存场景下只能被同一个线程操作,java并发处理提供ReentrantLock或Synchronized进行互斥控制。但是这仅仅对单机环境有效。我们实现分布式锁大概通过三种方式。 redis实现分布式锁 数据库实现...

    基于加权计数器限流算法的java计算限流工具

    许多需求计算量都在扩大, 针对大容量、高并发的接口、mq或者其他计算方法,同一时间在运行的计算维度进行限制,相当于把资源到计算的对象维度。 不同于参数限制,工具针对的是服务所有线程对于该计算维度的限流。...

    java核心知识点整理.pdf

    25 JAVA8 与元数据.................................................................................................................................25 2.4. 垃圾回收与算法 .................................

    8、读写锁ReentrantReadWriteLock&StampLock详解.pdf

    7、深入理解 AQS 独占锁之 Reentrantlock 源码分析 (1).pdf 8、读写锁ReentrantReadWriteLock&StampLock详解.pdf 9、并发容器 (Map、List、Set) 实战及其原理.pdf 10、阻塞队列BlockingQueue 实战及其原理分析.pdf

Global site tag (gtag.js) - Google Analytics