`

Java多线程基础总结八:ReentrantReadWriteLock

阅读更多

   说到ReentrantReadWriteLock,首先要做的是与ReentrantLock划清界限。它和后者都是单独的实现,彼此之间没有继承或实现的关系。 然后就是总结这个锁机制的特性了:
  • (a).重入方面其内部的WriteLock可以获取ReadLock,但是反过来ReadLock想要获得WriteLock则永远都不要想。
  • (b).WriteLock可以降级为ReadLock,顺序是:先获得WriteLock再获得ReadLock,然后释放WriteLock,这时候线程将保持Readlock的持 有。反过来ReadLock想要升级为WriteLock则不可能,为什么?参看(a),呵呵.
  • (c).ReadLock可以被多个线程持有并且在作用时排斥任何的WriteLock,而WriteLock则是完全的互斥。这一特性最为重要,因为对于高 读取频率而相对较低写入的数据结构,使用此类锁同步机制则可以提高并发量。
  • (d).不管是ReadLock还是WriteLock都支持Interrupt,语义与ReentrantLock一致。
  • (e).WriteLock支持Condition并且与ReentrantLock语义一致,而ReadLock则不能使用Condition,否则抛出 UnsupportedOperationException异常。
  • 以上就是比较重要的,或者衡量是否使用ReentrantReadWriteLock的基础了。下面还是写个小例子说明部分内容:


package thread;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReentrantReadWriteLockSample {

	public static void main(String[] args) {
		testReadLock();
		// testWriteLock();
	}

	public static void testReadLock() {
		final ReadWriteLockSampleSupport support = new ReadWriteLockSampleSupport();
		support.initCache();

		Runnable runnable = new Runnable() {
			public void run() {
				support.get("test");
			}
		};

		new Thread(runnable).start();
		new Thread(runnable).start();

		new Thread(new Runnable() {
			public void run() {
				support.put("test", "test");
			}
		}).start();
	}

	public static void testWriteLock() {
		final ReadWriteLockSampleSupport support = new ReadWriteLockSampleSupport();
		support.initCache();

		new Thread(new Runnable() {
			public void run() {
				support.put("key1", "value1");
			}
		}).start();

		new Thread(new Runnable() {
			public void run() {
				support.put("key2", "value2");
			}
		}).start();

		new Thread(new Runnable() {
			public void run() {
				support.get("key1");
			}
		}).start();
	}
}

class ReadWriteLockSampleSupport {
	private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
	private final Lock readLock = lock.readLock();
	private final Lock writeLock = lock.writeLock();

	private volatile boolean completed;
	private Map<String, String> cache;

	public void initCache() {
		readLock.lock();
		if (!completed) {
			// Must release read lock before acquiring write lock
			readLock.unlock(); // (1)
			writeLock.lock(); // (2)
			if (!completed) {
				cache = new HashMap<String, String>(32);
				completed = true;
			}
			// Downgrade by acquiring read lock before releasing write lock
			readLock.lock(); // (3)
			writeLock.unlock(); // (4) Unlock write, still hold read
		}

		System.out.println("empty? " + cache.isEmpty());
		readLock.unlock();
	}

	public String get(String key) {
		readLock.lock();
		System.out.println(Thread.currentThread().getName() + " read.");
		startTheCountdown();
		try {
			return cache.get(key);
		} finally {
			readLock.unlock();
		}
	}

	public String put(String key, String value) {
		writeLock.lock();
		System.out.println(Thread.currentThread().getName() + " write.");
		startTheCountdown();
		try {
			return cache.put(key, value);
		} finally {
			writeLock.unlock();
		}
	}

	/**
	 * A simple countdown,it will stop after about 5s.
	 */
	public void startTheCountdown() {
		long currentTime = System.currentTimeMillis();
		for (;;) {
			long diff = System.currentTimeMillis() - currentTime;
			if (diff > 5000) {
				break;
			}
		}
	}
}


  这个例子改造自JDK的API提供的示例,其中ReadWriteLockSampleSupport辅助类负责维护一个Map,当然前提是这个Map大部分的多线程 下都是读取,只有很少的比例是多线程竞争修改Map的值。其中的initCache()简单的说明了特性(a),(b).在这个方法中如果把注释(1)和(2) 处的代码调换位置,就会发现轻而易举的死锁了,当然是因为特性(1)的作用了。而注释(3),(4)处的代码位置则再次证明了特性 (a),并 且有力的反映了特性(b)--WriteLock在cache初始化完毕之后,降级为ReadLock。另外get(),put()方法在线程获取锁之后会在方法中呆上近 5s的时间。
  ReentrantReadWriteLockSample中的两个静态测试方法则分别测试了ReadLock和WriteLock的排斥性。testReadLock()中,开启三个线程 ,前两者试图获取ReadLock而后者去获取WriteLock。执行结果可以看到:ReadWriteLockSampleSupport的get()方法中的打印结果在前两个 线程中几乎同时显示,而put()中的打印结果则要等上近5s。这就说明了,ReadLock可以多线程持有并且排斥WriteLock的持有线程。 testWriteLock()中,也开启三个线程。前两个是去获取WriteLock,最后一个获取ReadLock。执行的结果是三个打印结果都有近5s的间隔时 间,这说明了WriteLock是独占的,比较独!


ref:http://www.bianceng.cn/Programming/Java/201206/34156.htm
分享到:
评论

相关推荐

    java 多线程编程实战指南(核心 + 设计模式 完整版)

    《Java多线程编程实战指南》这本书深入浅出地讲解了Java多线程的核心概念和实战技巧,分为核心篇和设计模式篇,旨在帮助开发者掌握并应用多线程技术。 1. **线程基础** - **线程的创建**:Java提供了两种创建线程...

    java多线程经典案例

    通过分析并实践`threadTest`案例,我们可以深入理解Java多线程的原理和使用技巧,为编写高效并发程序打下坚实基础。同时,也要注意多线程编程中的死锁、活锁和饥饿等问题,合理设计线程间的交互,避免出现不可预期的...

    Java 多线程学习总结6

    在“Java多线程学习总结6”这个主题中,我们可以深入探讨Java多线程的实现、管理及优化。下面将详细阐述相关知识点。 1. **线程的创建方式** - **继承Thread类**:自定义类继承Thread类,并重写run()方法,创建...

    java多线程设计模式_java_设计模式_多线程_多线程课题_

    Java多线程设计模式是Java开发中的核心概念,它涉及到如何高效、安全地在多个执行线程之间共享资源和协调任务。设计模式是解决特定问题的成熟方案,它们是编程经验的结晶,可以帮助开发者在面临多线程挑战时快速找到...

    java多线程、锁的教程跟案例

    Java多线程与锁是Java并发编程中的核心概念,它们对于构建高效、可扩展的并发应用程序至关重要。在Java中,多线程允许程序同时执行多个任务,提高CPU的利用率,而锁则是用来控制多线程间共享资源的访问,确保数据的...

    Java 多线程与并发编程总结.doc

    Java多线程与并发编程是Java开发中不可或缺的一部分,它涉及到如何高效地利用CPU资源,实现并发执行多个任务。在操作系统层面,多线程是为了提高系统利用率,使得多个任务能够"同时"执行,但实际上,由于CPU的时钟...

    Java多线程编程总结.pdf

    下面将对Java多线程编程的相关知识点进行详细的总结。 首先,我们需要理解线程的概念和原理。线程是操作系统分配CPU时间的基本单位,每个线程都有自己的程序计数器、虚拟机栈、本地方法栈和一部分堆内存。Java通过`...

    java多线程之并发锁

    Java 多线程之并发锁 Java 中的多线程编程是指在一个程序中同时运行多个线程,以提高程序的执行效率和响应速度。在多线程编程中,线程间的同步是非常重要的,因为不同的线程可能会同时访问同一个共享资源,导致数据...

    java多线程设计模式

    #### 一、Java多线程基础 Java语言自诞生以来,便内置了对多线程的支持。多线程可以让应用程序在同一时间处理多个任务,提高程序的执行效率和响应速度。Java中创建线程有两种基本方式: 1. **继承Thread类**: - ...

    java多线程设计模式详解(PDF及源码)

    首先,我们来了解一下Java多线程的基础知识。Java中的线程是程序执行的最小单位,通过多线程,程序可以同时执行多个任务,从而充分利用系统资源,提高效率。Java提供了多种创建线程的方式,包括继承Thread类、实现...

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

    在Java多线程并发编程中,ReentrantReadWriteLock(可重入读写锁)是一个重要的同步工具,它属于Java并发包(java.util.concurrent.locks)中的一个类。这个锁提供了比标准的synchronized关键字更细粒度的控制,允许...

    Java多线程源码笔记.pdf

    1. Thread类解析:Thread类是Java多线程的基础,它拥有start()方法来启动线程,run()方法用来执行线程的逻辑。通过重写run()方法,你可以定义线程执行的具体任务。 2. 使用多线程需要注意的问题:多线程环境下,...

    Java多线程总结.pdf

    Java多线程是指在Java语言中同时运行多个线程,从而实现对任务的并行处理。这是Java中一个非常重要的概念和技能,尤其在需要高并发处理和优化性能的场景中显得尤为重要。以下将详细梳理Java多线程编程中的一些关键...

    java多线程设计模式详解

    Java多线程设计模式是Java开发中不可或缺的一部分,它涉及到如何在并发环境下高效、安全地组织程序执行。本文将深入探讨几种常见的Java多线程设计模式,并通过源码解析来帮助理解其实现机制。 首先,我们要理解Java...

    Java多线程与高并发入门到精通-视频教程网盘链接提取码下载.txt

    综上所述,《Java多线程与高并发入门到精通》是一门全面涵盖Java多线程编程基础及高级技术的课程。无论您是初学者还是有一定基础的开发者,都能够从中获得宝贵的知识和经验。通过学习这门课程,您将能够掌握多线程的...

    java多线程安全性基础介绍.pptx

    java多线程安全性基础介绍 线程安全 正确性 什么是线程安全性 原子性 竞态条件 i++ 读i ++ 值写回i 可见性 JMM 由于cpu和内存加载速度的差距,在两者之间增加了多级缓存导致,内存并不能直接对cpu可见。 ...

    图灵图书:图解JAVA多线程设计模式

    - **Java多线程基础** - 线程的概念与创建方式 - 线程的状态及其转换 - 线程生命周期 - **Java并发编程** - 同步机制(synchronized关键字) - volatile关键字的作用 - 锁机制详解(Lock接口与ReentrantLock类...

Global site tag (gtag.js) - Google Analytics