0 0

java 读写互斥lock 实现缓存问题0


package cn.itcast.heima2;

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

public class CacheDemo {
	private static ReadWriteLock rwl = new ReentrantReadWriteLock(); //读写锁
	private static Map<String, Object> cache = new HashMap<String, Object>();
	public static void main(String[] args) {
		for(int j=0;j<10;j++){ //写入
			final String key= "key"+j;
			new Thread(new Runnable() {
				public void run() {
					 put(key,key);
				}
			}).start();
			new Thread(new Runnable() { //读取
				public void run() {
					Object data = getData(key);
					System.out.println(Thread.currentThread().getName()+"-- get data : {key:"+key+",value: "+data+"}");
				}
			}).start();
		}
	}
	//取
	public  static Object getData(String key){
		rwl.readLock().lock();
		Object value = null;
		try{
			value = cache.get(key);
			if(value == null){
				rwl.readLock().unlock();
				rwl.writeLock().lock();
				try{
					if(value==null){
						value = "no";//实际失去queryDB();
					}
				}finally{
					rwl.writeLock().unlock();
				}
				rwl.readLock().lock();
			}
		}finally{
			rwl.readLock().unlock();
		}
		return value;
	}
	//存
	public static void put(String key,Object value){
		rwl.writeLock().lock();
		System.out.println("begin of put data >>");
		try{
			Thread.sleep(1000);
			if(key != null){
				cache.put(key, value);
			}
			System.out.println(Thread.currentThread().getName()+"-- put data :  {key:"+key+",value: "+value+"}");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally{
			rwl.writeLock().unlock();
		}
		System.out.println("end of put data >>");
	}
}


打印结果如图所示:

在向缓存中写入数据的时候,读取缓存的线程应该等待 写入锁释放之后才进行读取才对。
也就是说,打印结果应该是:
     begin of put data >>
     Thread-0-- put data :  {key:key0,value: key0}
     end of put data >>
     Thread-3-- get data : {key:key0,value: key0}
才对。不知道以上代码哪里出问题了。还请大家帮我看看。
 
谢谢~~

问题补充:程序打印结果:
begin of put data >>
Thread-0-- put data :  {key:key0,value: key0}
Thread-3-- get data : {key:key1,value: no}
begin of put data >>
end of put data >>
Thread-4-- put data :  {key:key2,value: key2}
Thread-7-- get data : {key:key3,value: no}
begin of put data >>
end of put data >>
Thread-8-- put data :  {key:key4,value: key4}
end of put data >>
Thread-1-- get data : {key:key0,value: key0}
Thread-11-- get data : {key:key5,value: no}
begin of put data >>
Thread-12-- put data :  {key:key6,value: key6}
Thread-15-- get data : {key:key7,value: no}
begin of put data >>
end of put data >>
Thread-16-- put data :  {key:key8,value: key8}
end of put data >>
begin of put data >>
Thread-2-- put data :  {key:key1,value: key1}
Thread-5-- get data : {key:key2,value: key2}
end of put data >>
begin of put data >>
Thread-19-- get data : {key:key9,value: no}
Thread-6-- put data :  {key:key3,value: key3}
Thread-9-- get data : {key:key4,value: key4}
begin of put data >>
end of put data >>
Thread-10-- put data :  {key:key5,value: key5}
Thread-13-- get data : {key:key6,value: key6}
Thread-17-- get data : {key:key8,value: key8}
begin of put data >>
end of put data >>
Thread-14-- put data :  {key:key7,value: key7}
begin of put data >>
end of put data >>
Thread-18-- put data :  {key:key9,value: key9}
end of put data >>
2013年9月05日 16:11
  • 大小: 126 KB

2个答案 按时间排序 按投票排序

0 0

打印结果不应该是楼主描述的那样。end of put data >> 和 Thread-3-- get data 没在锁的保护范围内啊,这样打印顺序就没有任何保证了

2013年9月06日 16:44
0 0

没看出来问题啊,如果你的意思是为什么是先Thread-3-- get data : {key:key1,value: no},而不是 Thread-3-- get data : {key:key0,value: key0}的问题话?
主线程main只是负责启动了读写的线程,而不是说执行,你的get和put操作都不是在主线程执行的,无法保证他们顺序执行。

2013年9月06日 08:40

相关推荐

    多进程互斥读写XML文件

    - 在Python中,可以使用`threading.Lock`或`multiprocessing.Lock`来实现进程间的互斥锁。 - 在C++中,可以使用`std::mutex`(线程)或`std::shared_mutex`(读写锁)来控制对XML文件的访问。 7. **性能优化** -...

    Mysql(MyISAM)的读写互斥锁问题的解决方法

    MySQL中的MyISAM存储引擎在面对大量并发读写操作时,可能会出现严重的读写互斥锁问题。这种问题主要体现在,当写操作频繁时,由于MyISAM的锁机制,读操作会被阻塞,导致数据库性能急剧下降。尤其是在主从复制环境中...

    java面试题_缓存(10题)

    在Java面试中,缓存是经常被讨论的重要话题,因为它在...以上内容详细阐述了Java面试中关于缓存的常见问题及其解答,涵盖了缓存的基本概念、实现、策略、问题及解决方法,有助于理解和掌握缓存技术在实际项目中的应用。

    springboot缓存一致性解决

    例如,设置合理的缓存过期时间、使用随机盐值防止缓存穿透、以及使用互斥锁防止缓存雪崩和击穿。 10. **监控与调优**: 使用监控工具(如Spring Boot Actuator)监控缓存性能,及时发现并解决问题,通过调整缓存...

    Java的两种读写锁介绍

    在Java并发编程中,读写锁是用于优化多线程访问共享资源的一种机制,它可以提高对数据的并发访问效率。本文将深入探讨Java中的两种读写锁:ReentrantReadWriteLock和StampedLock,并分析它们的工作原理、特点以及...

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

    - **读写互斥**:当有一个线程正在进行写操作时,不允许其他线程进行读或写操作。 - **写写互斥**:同一时间只允许一个线程进行写操作。 #### 1.2 读写锁的特点 - **可重入性**:允许已经拥有某个锁的线程再次获取...

    C++开发在IOS环境下运行的LRUCache缓存功能.pdf

    总结来说,这篇文档主要介绍了如何在iOS的C++环境中实现LRUCache缓存功能,包括LRU算法的原理,使用两个MAP对象实现LRU队列,以及使用Singleton模式和读写互斥锁保证线程安全。这样的实现能够有效地提升iOS应用的...

    多线程(22)读写锁分离模式1

    Java中提供了`java.util.concurrent.locks.ReadWriteLock`接口来支持这种模式,但在本案例中,我们将模拟实现一个读写锁来理解其基本原理。 1. **读写锁接口定义**: - `Lock`接口:这是基础的锁接口,提供了获取...

    Java并发编程全景图.pdf

    为了深入理解Java并发编程,有必要了解其核心技术点和相关实现原理,以下将详细介绍文件中提及的关键知识点。 1. Java同步原语 Java提供了多种同步原语来保证线程安全,主要包括关键字volatile、synchronized以及...

    基于consul的分布式锁工具,包含:互斥锁、信号量等工具

    本项目利用Consul的KV存储功能,构建了一套Java实现的分布式锁工具,包括互斥锁和信号量,旨在简化在分布式环境中的同步操作。 1. **Consul简介** Consul是由HashiCorp公司开发的一款服务发现与配置工具,它具备...

    构建高效可伸缩的缓存demo

    可以使用锁机制,如互斥锁(Mutex)或读写锁(Read-Write Lock),或者使用无锁数据结构,如Java中的ConcurrentHashMap。 3. **分布式缓存**:当单机缓存无法满足需求时,我们可以采用分布式缓存,如Redis或...

    深入理解Java内存模型 pdf 超清版

    - 使用`Lock`接口及其实现(如`ReentrantLock`) - 线程局部变量(`ThreadLocal`) 8. **线程状态转换** - 新建(New)、就绪(Runnable)、运行(Running)、等待(Blocked/Waiting)、阻塞(Timed_Waiting/...

    互联网高频Java后端面试题20道(适合1~3年)V1.0.57.docx

    为了避免这些问题,可以采用布隆过滤器防止缓存穿透,设置合理的缓存过期时间避免雪崩,以及使用互斥锁防止缓存击穿。 问题 13:Java 中的集合框架有哪些主要的类?它们各自适用于什么场景?答案:Java 集合框架...

    C++开发在IOS环境下运行的LRUCache缓存功能.docx

    为了解决这个问题,代码中引入了一个简单的读写互斥锁`rwlock`。读写锁允许多个读者同时访问,但只允许一个写者,从而避免了数据竞争。`LOCK`和`UNLOCK`宏用于获取和释放锁,而`rwlock_rlock`和`rwlock_wlock`函数...

    15个顶级Java多线程面试题及回答

    - **题目**: 用Java实现阻塞队列。 - **解析**: 阻塞队列是一种特殊的队列,当队列为空时,获取元素的操作会等待队列变为非空;当队列满时,存储元素的操作会等待队列中有可用空间。Java提供了多种实现阻塞队列的...

    java常见面试题汇总和解答

    3. **线程与并发**:线程是Java实现并发处理的关键,面试中可能会考察线程的创建、状态转换、同步机制(synchronized、wait/notify、Lock接口)以及死锁和活锁的预防。 4. **锁机制**:Java提供了多种锁,如内置锁...

    java面试题_高并发、高可用、分布式(9题)

    - **读写锁**:ReentrantReadWriteLock允许多个读操作同时进行,但写操作互斥。 - **单例模式**:在多线程环境下,双重检查锁定(Double-Check Locking)是实现线程安全的单例模式。 5. **JVM优化** 面对高并发...

    计算机软件-商业源码-利用读写锁保持线程同步.zip

    读写锁的概念源于操作系统理论,但在许多编程语言中都有实现,如Java的`java.util.concurrent.locks.ReentrantReadWriteLock`和C++的`std::shared_timed_mutex`。下面将详细探讨读写锁的工作原理、优缺点以及如何在...

    SemQueue_多线程_缓存队列_

    - **线程安全的数据结构**:为了确保并发访问的正确性,"SemQueue"的队列结构应该设计为线程安全的,这意味着所有对队列的操作都应考虑锁的使用,例如互斥锁(Mutex)或者读写锁(Read-Write Lock)。 2. **缓存...

    实战Java高并发程序设计模式高清视频教程.zip

    在设计模式方面,我们会学习到一些经典的并发模式,如生产者消费者模式(Producer-Consumer)、读写锁模式(Read-Write Lock)和双检锁/双重校验锁(Double-Checked Locking)。这些模式有助于我们在实际项目中优雅...

Global site tag (gtag.js) - Google Analytics