-
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
2个答案 按时间排序 按投票排序
-
打印结果不应该是楼主描述的那样。end of put data >> 和 Thread-3-- get data 没在锁的保护范围内啊,这样打印顺序就没有任何保证了
2013年9月06日 16:44
-
没看出来问题啊,如果你的意思是为什么是先Thread-3-- get data : {key:key1,value: no},而不是 Thread-3-- get data : {key:key0,value: key0}的问题话?
主线程main只是负责启动了读写的线程,而不是说执行,你的get和put操作都不是在主线程执行的,无法保证他们顺序执行。2013年9月06日 08:40
相关推荐
- 在Python中,可以使用`threading.Lock`或`multiprocessing.Lock`来实现进程间的互斥锁。 - 在C++中,可以使用`std::mutex`(线程)或`std::shared_mutex`(读写锁)来控制对XML文件的访问。 7. **性能优化** -...
MySQL中的MyISAM存储引擎在面对大量并发读写操作时,可能会出现严重的读写互斥锁问题。这种问题主要体现在,当写操作频繁时,由于MyISAM的锁机制,读操作会被阻塞,导致数据库性能急剧下降。尤其是在主从复制环境中...
在Java面试中,缓存是经常被讨论的重要话题,因为它在...以上内容详细阐述了Java面试中关于缓存的常见问题及其解答,涵盖了缓存的基本概念、实现、策略、问题及解决方法,有助于理解和掌握缓存技术在实际项目中的应用。
例如,设置合理的缓存过期时间、使用随机盐值防止缓存穿透、以及使用互斥锁防止缓存雪崩和击穿。 10. **监控与调优**: 使用监控工具(如Spring Boot Actuator)监控缓存性能,及时发现并解决问题,通过调整缓存...
在Java并发编程中,读写锁是用于优化多线程访问共享资源的一种机制,它可以提高对数据的并发访问效率。本文将深入探讨Java中的两种读写锁:ReentrantReadWriteLock和StampedLock,并分析它们的工作原理、特点以及...
- **读写互斥**:当有一个线程正在进行写操作时,不允许其他线程进行读或写操作。 - **写写互斥**:同一时间只允许一个线程进行写操作。 #### 1.2 读写锁的特点 - **可重入性**:允许已经拥有某个锁的线程再次获取...
总结来说,这篇文档主要介绍了如何在iOS的C++环境中实现LRUCache缓存功能,包括LRU算法的原理,使用两个MAP对象实现LRU队列,以及使用Singleton模式和读写互斥锁保证线程安全。这样的实现能够有效地提升iOS应用的...
Java中提供了`java.util.concurrent.locks.ReadWriteLock`接口来支持这种模式,但在本案例中,我们将模拟实现一个读写锁来理解其基本原理。 1. **读写锁接口定义**: - `Lock`接口:这是基础的锁接口,提供了获取...
为了深入理解Java并发编程,有必要了解其核心技术点和相关实现原理,以下将详细介绍文件中提及的关键知识点。 1. Java同步原语 Java提供了多种同步原语来保证线程安全,主要包括关键字volatile、synchronized以及...
本项目利用Consul的KV存储功能,构建了一套Java实现的分布式锁工具,包括互斥锁和信号量,旨在简化在分布式环境中的同步操作。 1. **Consul简介** Consul是由HashiCorp公司开发的一款服务发现与配置工具,它具备...
可以使用锁机制,如互斥锁(Mutex)或读写锁(Read-Write Lock),或者使用无锁数据结构,如Java中的ConcurrentHashMap。 3. **分布式缓存**:当单机缓存无法满足需求时,我们可以采用分布式缓存,如Redis或...
- 使用`Lock`接口及其实现(如`ReentrantLock`) - 线程局部变量(`ThreadLocal`) 8. **线程状态转换** - 新建(New)、就绪(Runnable)、运行(Running)、等待(Blocked/Waiting)、阻塞(Timed_Waiting/...
为了避免这些问题,可以采用布隆过滤器防止缓存穿透,设置合理的缓存过期时间避免雪崩,以及使用互斥锁防止缓存击穿。 问题 13:Java 中的集合框架有哪些主要的类?它们各自适用于什么场景?答案:Java 集合框架...
为了解决这个问题,代码中引入了一个简单的读写互斥锁`rwlock`。读写锁允许多个读者同时访问,但只允许一个写者,从而避免了数据竞争。`LOCK`和`UNLOCK`宏用于获取和释放锁,而`rwlock_rlock`和`rwlock_wlock`函数...
- **题目**: 用Java实现阻塞队列。 - **解析**: 阻塞队列是一种特殊的队列,当队列为空时,获取元素的操作会等待队列变为非空;当队列满时,存储元素的操作会等待队列中有可用空间。Java提供了多种实现阻塞队列的...
3. **线程与并发**:线程是Java实现并发处理的关键,面试中可能会考察线程的创建、状态转换、同步机制(synchronized、wait/notify、Lock接口)以及死锁和活锁的预防。 4. **锁机制**:Java提供了多种锁,如内置锁...
- **读写锁**:ReentrantReadWriteLock允许多个读操作同时进行,但写操作互斥。 - **单例模式**:在多线程环境下,双重检查锁定(Double-Check Locking)是实现线程安全的单例模式。 5. **JVM优化** 面对高并发...
读写锁的概念源于操作系统理论,但在许多编程语言中都有实现,如Java的`java.util.concurrent.locks.ReentrantReadWriteLock`和C++的`std::shared_timed_mutex`。下面将详细探讨读写锁的工作原理、优缺点以及如何在...
- **线程安全的数据结构**:为了确保并发访问的正确性,"SemQueue"的队列结构应该设计为线程安全的,这意味着所有对队列的操作都应考虑锁的使用,例如互斥锁(Mutex)或者读写锁(Read-Write Lock)。 2. **缓存...
在设计模式方面,我们会学习到一些经典的并发模式,如生产者消费者模式(Producer-Consumer)、读写锁模式(Read-Write Lock)和双检锁/双重校验锁(Double-Checked Locking)。这些模式有助于我们在实际项目中优雅...