`

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(); 并不是表示线程启动的顺序,就是线程获得锁的顺序)

分享到:
评论
2 楼 Glogo 2013-11-28  
楼主您好,我在试验您的代码的时候发现新开的三个子线程并没有一直在竞争,而是被0号子线程一直占据着,请问是怎么回事?是机器的原因么?
1 楼 liuyuanhui0301 2012-06-18  
 

相关推荐

    Java多线程高并发篇(一)--重入锁

    在Java多线程高并发编程中,重入锁(ReentrantLock)是一个至关重要的概念,它提供了比Java内置锁(synchronized)更细粒度的控制,并且具有更高的可读性和可扩展性。本篇文章将深入探讨重入锁的相关知识点。 首先...

    Java 多线程与并发(11-26)-JUC锁- ReentrantLock详解.pdf

    Java中的ReentrantLock是Java并发包(java.util.concurrent.locks)中的一个高级锁,它是可重入的,意味着一个线程可以多次获取同一锁。在深入ReentrantLock之前,我们首先需要了解Java并发编程的基础,特别是Java...

    Java高并发经典文档-PDF-可在电子书里查看

    另外,`ReentrantLock`是可重入锁,提供了比`synchronized`更灵活的锁定机制。 4. **并发容器**:`ArrayList`、`LinkedList`等集合在并发环境下可能存在安全问题,因此,Java提供了线程安全的集合类,如`Vector`、`...

    实战Java高并发程序设计-试读

    《实战Java高并发程序设计》是一本专注于Java并发编程实践的书籍,试读版提供了前两章的内容,为读者提供了一个初步了解并发编程基础的窗口。在Java领域,并发编程是构建高性能、高效率系统的关键技术,对于软件开发...

    实战Java高并发程序设计第二版随书代码

    《实战Java高并发程序设计》第二版是一本深入探讨Java多线程和并发编程的书籍。这本书涵盖了Java并发编程的核心概念和技术,旨在帮助开发者在实际项目中高效地处理高并发场景。随书附带的代码提供了丰富的示例,以便...

    Java多线程之ReentrantLock与Condition - 平凡希 - 博客园1

    Java中的`ReentrantLock`是Java并发包`java.util.concurrent.locks`中的一个高级锁机制,它是可重入的互斥锁,具有与`synchronized`关键字相似的同步性,但提供了更多的灵活性和控制功能。本篇文章将深入探讨`...

    实战Java高并发程序设计-随书代码

    《实战Java高并发程序设计》是一本专注于Java并发编程实践的书籍,随书代码提供了大量示例,帮助读者深入理解并掌握在实际开发中如何处理高并发场景下的问题。本书的核心知识点涵盖了Java并发编程的基础理论、核心...

    java高并发程序设计(原版电子书)

    《Java高并发程序设计》是一本深入探讨Java平台上的并发编程技术的专业书籍,由葛一鸣等人编著。这本书旨在帮助读者理解并掌握在高并发环境下编写高效、稳定且可扩展的Java应用程序的关键技巧和最佳实践。以下是该书...

    Java并发锁简介-动力节点共9页.pdf.zip

    2. ** ReentrantLock**: 实现了Lock接口,具有可重入特性,即线程可以多次获取同一锁,不会造成死锁。 3. ** 公平锁与非公平锁**: ReentrantLock支持两种模式,公平锁按照线程等待的顺序分配锁,而非公平锁则无此...

    Java高并发视频教学,并带实战java高并发程序设计,高并发面试题目

    Java高并发编程是Java开发中的重要领域,尤其在大规模分布式系统和互联网应用中,对高并发处理能力的要求日益提升。本资源包含了一套完整的Java高并发视频教学,以及相关的实战项目和面试题目,旨在帮助开发者深入...

    java 高并发解决 思路

    以上只是Java高并发解决思路的一部分,实际应用中还需要结合具体业务场景和性能需求进行选择和优化。"高并发web架构.pdf"文档中的实例将进一步细化这些概念,提供实践指导。在学习过程中,理论与实践相结合,才能更...

    Java并发编程实践-07章-显示锁1

    `ReentrantLock`是`Lock`接口的实现,它具有可重入性,意味着一个线程可以多次获取同一锁,只要该线程未释放所有的锁。这与`synchronized`关键字的行为相同,即在同一个线程中,嵌套的`synchronized`块可以自由进入...

    java ReentrantLock详解.docx

    `ReentrantLock`是Java并发编程中的一种高级锁机制,它是`java.util.concurrent.locks`包中的类,提供了比`synchronized`关键字更丰富的功能和更细粒度的控制。相较于`synchronized`,`ReentrantLock`的主要优势在于...

    java高并发系统设计

    在本文中,我们将深入探讨Java高并发系统设计的相关知识点,包括基础概念、核心技术以及最佳实践。 1. **并发编程基础** - **线程与进程**:线程是操作系统调度的基本单位,而进程则是拥有独立资源的执行单元。 -...

    Java源码解析之可重入锁ReentrantLock

    Java源码解析之可重入锁ReentrantLock ReentrantLock是一个可重入锁,在ConcurrentHashMap中使用了ReentrantLock。它是一个可重入的排他锁,它和synchronized的方法和代码有着相同的行为和语义,但有更多的功能。 ...

    java高并发编程推荐超好的一本电子书

    根据提供的信息,我们可以深入探讨Java高并发编程的相关知识点。高并发是现代软件系统设计中一个非常重要的方面,尤其是在云计算和大数据处理领域。下面将详细解释Java高并发编程的基础概念、核心技术以及实现技巧。...

Global site tag (gtag.js) - Google Analytics