《黑马程序员》 读写锁之缓存系统

------- android培训java培训、期待与您交流! ----------
public class CachedDemo {
	/**
	 * 缓存系统 
	 *     既然是存的缓存系统里面存储的就不是一个对象
	 *     就是别人想要获取某个对象的时候,可以通过我们的缓存系统去进行查找
	 *     我们先查找当前的缓存系统中是否有这个对象
	 *     如果有就返回该对象。如果没有就查找数据库
	 */
	//把对象存储在map集合中
	private Map<String,Object> map=new HashMap<String,Object>();
	public static void main(String[] args) {
       
	}
	
	//现在我们来使用读写锁来改写代码
	private ReadWriteLock rwl=new ReentrantReadWriteLock();
	public synchronized Object getData(String key){ //别人是通过key来获取对象
		//一上来就上读锁
		rwl.readLock().lock(); //上读锁所有的线程都是可以读的。所以线程都可以到这里来
		Object obj=null;  //局部变量在使用的时候一定要先初始化
		try {
			obj = map.get(key);
			if (obj == null) {
				//如果有一个线程发现数据为空了的话。就把读锁释放掉。要填充数据
				rwl.readLock().unlock();
				//上写锁开始写数据
				rwl.writeLock().lock();  //这样其它的线程都被堵在外面了
				try{
				    if(obj==null){
				    	obj = "query db"; //实际上是我们在这里就要去数据库中进行查找了
				    }
				}catch(Exception e){
					e.printStackTrace();
				}finally{
					//数据填充完之后把写锁给释放掉
					rwl.writeLock().unlock();
					//把读锁恢复
					rwl.readLock().lock();
				}
			}
		} catch (Exception e) {
			// TODO: handle exception
		}finally{
			rwl.readLock().unlock();  //全部读完之后把读锁给释放掉
		}
		return obj; //这样下次再来查找的时候,如果数据是存在的就不用再查找数据库而是直接返回该数据了
	}
	//要让多个线程访问的时候产生互斥要使用synchronized将这个方法进行互斥
	
/*	我们在上面的时候发现了一个问题,如果有三个线程,它们都进来了。第一个线程发现数据为空,把锁给释放掉了
	其它的线程把就把锁都给释放掉了。然后它上了写锁,这样其它的线程是堵在外面的,它在填充完数据之后,把写锁给
	释放掉了,然后恢复了读锁的状态。第一个线程执行完之后,第二个线程,他也判断数据为空,它也进来了。它把读锁给释放掉了
	然后也也了写锁,然后给对象重复的赋值了。所以我们为了避免这类情况的发生。在对象填充数据的语句外面再进行一次判断。
	即线程是在上了写锁之后,如果数据为空的时候,才填充数据。不为空则不填充。
	这项是来自于:
	class CachedData {
		   Object data;
		   volatile boolean cacheValid;
		   ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();

		   void processCachedData() {
		     rwl.readLock().lock();
		     if (!cacheValid) {
		        // Must release read lock before acquiring write lock
		        rwl.readLock().unlock();
		        rwl.writeLock().lock();
		        // Recheck state because another thread might have acquired
		        //   write lock and changed state before we did.
		        if (!cacheValid) {
		          data = ...
		          cacheValid = true;
		        }
		        // Downgrade by acquiring read lock before releasing write lock
		        rwl.readLock().lock();
		        rwl.writeLock().unlock(); // Unlock write, still hold read
		     }

		     use(data);
		     rwl.readLock().unlock();
		   }
		 }*/
}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
很高兴您对Redis感兴趣!Redis是一款开源的内存数据库,它以键值对的方式存储数据,并提供了丰富的数据结构和功能。以下是关于Redis的一些笔记: 1. Redis的应用场景:Redis被广泛应用于缓存、消息队列、排行榜、计数器、分布式锁等场景,因为它具备高性能、高并发、持久化和分布式特性。 2. 数据结构:Redis支持多种数据结构,包括字符串、哈希表、列表、集合和有序集合。这些数据结构可以满足不同的业务需求。 3. 缓存:Redis做为缓存的优势在于它将数据存储在内存中,读写速度非常快。可以通过设置过期时间、LRU算法等来控制缓存的失效策略。 4. 持久化:Redis提供了两种持久化方式,分别是RDB和AOF。RDB是将内存中的数据定期保存到磁盘中,AOF则是将每条写命令追加到文件末尾。 5. 主从复制:Redis支持主从复制机制,当主节点发生故障时,从节点可以顶替主节点继续提供服务。主从复制还可以用于读写分离,提高系统并发能力。 6. 事务:Redis支持简单的事务操作,通过MULTI和EXEC命令可以将多个命令封装为一个事务进行执行,保证了操作的原子性。 7. Lua脚本:Redis支持通过Lua脚本的方式执行一系列命令,可以在服务端实现复杂逻辑,减少网络开销。 这些只是Redis的一些基础知识,如果您对特定的问题或者进一步深入了解Redis有兴趣,我可以为您提供更多的信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值