`
cuisuqiang
  • 浏览: 3962628 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
3feb66c0-2fb6-35ff-968a-5f5ec10ada43
Java研发技术指南
浏览量:3672021
社区版块
存档分类
最新评论

Java中锁的应用之-ReadWriteLock

    博客分类:
  • JDK
阅读更多

上面我们用儿子和父亲做了一个例子,儿子太猖狂了,花钱根本没有谱。

下面我们再做一个例子,讲解ReadWriteLock的使用,例子和刚才差不多,但是又多了一个角色母亲,而且父母只负责监督,不再存钱。

儿子每三秒都会去花钱一次,而父母每秒都在监督这个卡的使用情况。

 

所有 ReadWriteLock 实现都必须保证 writeLock 操作的内存同步效果也要保持与相关 readLock 的联系。也就是说,成功获取读锁的线程会看到写入锁之前版本所做的所有更新。

与互斥锁相比,读-写锁允许对共享数据进行更高级别的并发访问。虽然一次只有一个线程(writer 线程)可以修改共享数据,但在许多情况下,任何数量的线程可以同时读取共享数据(reader 线程),读-写锁利用了这一点。从理论上讲,与互斥锁相比,使用读-写锁所允许的并发性增强将带来更大的性能提高。在实践中,只有在多处理器上并且只在访问模式适用于共享数据时,才能完全实现并发性增强。

在 writer 释放写入锁时,reader 和 writer 都处于等待状态,在这时要确定是授予读取锁还是授予写入锁。Writer 优先比较普遍,因为预期写入所需的时间较短并且不那么频繁。Reader 优先不太普遍,因为如果 reader 正如预期的那样频繁和持久,那么它将导致对于写入操作来说较长的时延。公平或者“按次序”实现也是有可能的。

在 reader 处于活动状态而 writer 处于等待状态时,确定是否向请求读取锁的 reader 授予读取锁。Reader 优先会无限期地延迟 writer,而 writer 优先会减少可能的并发。

 

我们创建信用卡类:

package com.entity;
public class BankCard {	
	private String cardid = "XZ456789";	
	private int balance = 10000;
	public String getCardid() {
		return cardid;
	}
	public void setCardid(String cardid) {
		this.cardid = cardid;
	}
	public int getBalance() {
		return balance;
	}
	public void setBalance(int balance) {
		this.balance = balance;
	}
}

 

里面有卡号和父母已经存的钱。

儿子花钱首先要获得写的锁把卡锁了,然后再花钱。之后放开这个锁。

package com.thread;
import java.util.concurrent.locks.ReadWriteLock;
import com.entity.BankCard;
/**
 * @说明 儿子类,只消费
 */
public class Consumer implements Runnable {
	BankCard bc = null;
	ReadWriteLock lock = null;
	Consumer(BankCard bc, ReadWriteLock lock) {
		this.bc = bc;
		this.lock = lock;
	}
	public void run() {
		try {
			while(true){
				lock.writeLock().lock(); 
				System.out.print("儿子要消费,现在余额:" + bc.getBalance() + "\t");
				bc.setBalance(bc.getBalance() - 2000);
				System.out.println("儿子消费2000元,现在余额:" + bc.getBalance());
				lock.writeLock().unlock(); 
				Thread.sleep(3 * 1000);	
			}
		} catch (Exception e) {
			e.printStackTrace();
		}		
	}
}

父母类只监督这个卡的使用,获得的是读的锁。

package com.thread;
import java.util.concurrent.locks.ReadWriteLock;
import com.entity.BankCard;
/**
 * @说明 父母类,只监督
 */
public class Consumer2 implements Runnable {
	BankCard bc = null;
	int type = 0;
	ReadWriteLock lock = null;
	Consumer2(BankCard bc, ReadWriteLock lock,int type) {
		this.bc = bc;
		this.lock = lock;
		this.type = type;
	}
	public void run() {
		try {
			while(true){
				lock.readLock().lock(); 
				if(type==2)
					System.out.println("父亲要查询,现在余额:" + bc.getBalance());
				else
					System.out.println("老妈要查询,现在余额:" + bc.getBalance());
				//lock.readLock().unlock();
				Thread.sleep(1 * 1000);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}		
	}
}

 运行程序,儿子开始花钱,父母两人一直在查看花钱情况。

package com.thread;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import com.entity.BankCard;
public class MainThread {
	public static void main(String[] args) {
		BankCard bc = new BankCard();
		ReadWriteLock lock = new ReentrantReadWriteLock();
		ExecutorService pool = Executors.newCachedThreadPool();
		Consumer cm1 = new Consumer(bc, lock);
		Consumer2 cm2 = new Consumer2(bc, lock , 1);
		Consumer2 cm3 = new Consumer2(bc, lock , 2);
		pool.execute(cm1);
		pool.execute(cm2);
		pool.execute(cm3);
	}
}

 我们来看一下运行结果:

儿子要消费,现在余额:10000	儿子消费2000元,现在余额:8000
老妈要查询,现在余额:8000
父亲要查询,现在余额:8000
父亲要查询,现在余额:8000
老妈要查询,现在余额:8000
老妈要查询,现在余额:8000
父亲要查询,现在余额:8000
儿子要消费,现在余额:8000	儿子消费2000元,现在余额:6000
父亲要查询,现在余额:6000
老妈要查询,现在余额:6000
老妈要查询,现在余额:6000
父亲要查询,现在余额:6000
父亲要查询,现在余额:6000
老妈要查询,现在余额:6000
老妈要查询,现在余额:6000
儿子要消费,现在余额:6000	儿子消费2000元,现在余额:4000
父亲要查询,现在余额:4000

 读写锁是互斥的,但是对于读来说没有互斥性。

也就是说读和写必须分开,但是资源可以同时被几个线程访问。不管是读还是写没有释放锁,其他线程就一直等待锁的释放。

我们来注释父母监督时锁的释放:

lock.readLock().unlock();

 

儿子要消费,现在余额:10000	儿子消费2000元,现在余额:8000
父亲要查询,现在余额:8000
老妈要查询,现在余额:8000
老妈要查询,现在余额:8000
父亲要查询,现在余额:8000
老妈要查询,现在余额:8000
父亲要查询,现在余额:8000
老妈要查询,现在余额:8000
父亲要查询,现在余额:8000

 可以看到儿子花了一次钱后,父母把卡给锁了,儿子不能在花钱,但是父母两个人都可以一直查询卡的余额。 

 

请您到ITEYE看我的原创:http://cuisuqiang.iteye.com

或支持我的个人博客,地址:http://www.javacui.com

 

分享到:
评论
2 楼 姑苏痴情 2012-05-10  
如何跟Condition联合在一起用呢?
1 楼 cuisuqiang 2012-03-20  

相关推荐

    homework-ReadWriteLock-KristampsW-main.zip

    在Java中,`java.util.concurrent.locks.ReadWriteLock`接口提供了这种功能,它有两个主要的方法:`readLock()` 和 `writeLock()`. 这两个方法分别返回一个读锁和写锁,它们可以被不同的线程独立获取和释放,从而...

    Java中的ReadWriteLock:深入解析与应用实践

    ReadWriteLock 是Java并发编程中一个强大的工具,它通过分离读锁和写锁,允许多个线程并发地读取共享数据,同时保证了写操作的互斥性。这种机制特别适合于读多写少的场景,可以显著提高程序的性能和吞吐量。在使用 ...

    java进阶提高学习教程-14锁机制.pptx

    在 Java 中,锁有多种不同的实现机制,如可重入锁、读写锁、互斥锁、悲观锁、乐观锁、公平锁、锁消除、独享锁、共享锁等。 可重入锁 可重入锁,也叫做递归锁,指的是同一线程外层函数获得锁之后,内层递归函数仍然...

    java 读写锁代码

    Java 读写锁是Java并发编程中的一种重要机制,它为多线程环境下的数据访问提供了更为精细的控制。在Java的`java.util....通过阅读和分析`readwritelock`这个示例,开发者可以更好地掌握如何在Java中使用读写锁。

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

    1. **内置锁(Synchronized)**:这是Java中最基本的锁机制,通过关键字`synchronized`实现。它提供了对方法或代码块的互斥访问,确保同一时刻只有一个线程能够执行特定代码。内置锁在退出同步块或方法时自动释放,...

    23 按需上锁—ReadWriteLock详解.pdf

    《Java并发编程学习宝典(漫画版)》中提到的23章主要讲解了Java并发编程中的一个重要概念——ReadWriteLock,即读写锁。ReadWriteLock是`java.util.concurrent.locks`包下的一个接口,它是对传统互斥锁的一个扩展,...

    Java并发编程实践-电子书-03章

    ### Java并发编程实践-电子书-03章知识点解析 #### 3.1 java.util....通过以上章节的详细讲解,读者可以深入理解Java并发编程的核心概念和技术,掌握在多线程环境中编写高性能、高可靠性的应用程序所需的关键技能。

    Java锁的种类以及区别

    本文将详细介绍Java中几种常见的锁类型及其之间的区别。 #### 一、公平锁与非公平锁 **1. 公平锁** 公平锁遵循先进先出的原则,即线程获取锁的顺序与其请求锁的顺序相同。这种锁可以确保没有线程被饿死,但同时也...

    Java并发编程实践--电子书.rar

    在Java中,线程是并发的基础,它代表了程序中的独立执行流。Java提供了多种方式来创建和管理线程,包括继承Thread类和实现Runnable接口。通过线程池(如ExecutorService)可以有效地管理和调度大量线程,避免频繁...

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

    在Java中,多线程允许程序同时执行多个任务,提高CPU的利用率,而锁则是用来控制多线程间共享资源的访问,确保数据的一致性和完整性。 一、Java多线程 1. **线程创建方式** - 继承Thread类:自定义类继承Thread类...

    Java 多线程与并发(3-26)-Java 并发 - Java中所有的锁.pdf

    本文主要探讨了Java中的两种广义锁概念——乐观锁和悲观锁,以及自旋锁和适应性自旋锁的区别和应用场景。 1. 乐观锁与悲观锁: 乐观锁认为在读取数据时不会有其他线程修改,因此在读取时不加锁,而在更新数据时检查...

    Java的锁机制的学习和使用

    Java中的锁机制主要用于解决多线程环境下的资源竞争问题。在并发编程中,为了保证数据一致性与正确性,通常需要采用各种锁来控制对共享资源的访问。Java语言提供了多种锁机制,包括`synchronized`关键字、`...

    Java锁机制详解.pdf

    在Java中,内置锁是通过synchronized关键字实现的,而显示锁则是通过java.util.concurrent.locks包中的接口和类实现的。显示锁的一个重要接口是Lock,它提供了对锁操作的更细粒度控制,而ReentrantLock是Lock的一个...

    提升Java的锁性能Java开发Java经验技巧共5页.p

    - **内置锁(Synchronized)**:Java中的内置锁是通过关键字`synchronized`实现的,它提供了对方法或代码块的互斥访问,确保同一时间只有一个线程执行。 - **显式锁(Lock)**:Java并发包`java.util.concurrent....

    25个java热点面试题

    Java 中的锁 - **定义**:锁是一种同步机制,用于控制多线程间的访问权限。 - **常见锁类型**: - **悲观锁**:假设会发生冲突,每次访问都需要获取锁。 - **乐观锁**:假设不会发生冲突,通常使用 CAS 操作。 ...

    Java多线程编程总结

    - 在Java中,“线程”有两层含义: - `java.lang.Thread` 类的一个实例。 - 线程的执行过程。 - 使用 `java.lang.Thread` 类或 `java.lang.Runnable` 接口来定义、实例化和启动新线程。 - 每个Java应用从main()...

    java常用锁使用demo工程

    "java常用锁使用demo工程"是一个实践项目,旨在帮助开发者理解并熟练掌握Java中的锁机制。在这个工程中,我们可能会看到各种锁的实例,如内置锁(synchronized)、显式锁(java.util.concurrent.locks包中的Lock接口...

Global site tag (gtag.js) - Google Analytics