并发编程学习:使用读写锁来编写高效率的缓存系统

示例模板
package com.lei.lock;/*
*@author leixingbang_sx
*Mail:[email protected]
*@create 2016/1/20 10:22
*desc  缓存例子  
*/

import java.util.Random;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class CachedData {

    volatile  boolean cacheValid;//是否被缓存
    ReadWriteLock rwl=new ReentrantReadWriteLock();//可重入读写锁  *****位置M*******
    public void processCachedData()//处理缓存的数据
    {
        Object data=null;//注意这里的data是线程私有的,而cacheMap是所有线程公用的
        //所以只需要考虑cacheMap的读写锁的问题,而不需要考虑data
        rwl.readLock().lock();//读锁上锁
        if(!this.cacheValid)//在缓存中并不存在     ********位置A********
        {
            //1首先必须释放读锁,因为接下来需要从其他地方读取数据并写入。读写锁是互斥的
            rwl.readLock().unlock();
            //2写锁上锁
            rwl.writeLock().lock();//位置获取写锁   ********位置B********
            //3再次检测是否在缓存中存在数据,原因是可能存在一个线程在当前线程执行到位置A与位置B之间的时候
            //获取了写锁,并写入数据将cachedValid状态改变
            if(!this.cacheValid){
                data=this.getData();//模拟从数据库或者文件系统等获取数据
                this.cacheValid=true;//将状态更改为缓存系统中已经存在该数据
            }
            //4 在释放写锁之前先进行降级 为了保证使用数据时,数据本身不被改变,需要读锁上锁,然后才释放写锁
            // ********此处设计小知识点:当前线程自己的读锁和写锁并不冲突******
            rwl.readLock().lock();//                       *****位置N*******
            //*********开始持有读锁***********************
            rwl.writeLock().unlock();//释放写锁
        }
        use(data);
        rwl.readLock().unlock();//释放读锁 在位置M、N处,读锁都进行了加锁所以这里需要将锁释放
    }
    public  Integer getData()
    {
        Integer a=new Random().nextInt(1000);
        return a;
    }
    public void use(Object data)//使用数据
    {
        System.out.println(data);
    }

    public static void main(String[] args) {

    }

}

实际例子:

package com.lei.lock;/*
*@author leixingbang_sx
*Mail:[email protected]
*@create 2016/1/20 10:22
*desc  缓存例子  
*/

import java.util.Random;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class CachedData {

    volatile  boolean cacheValid;//是否被缓存
    ReadWriteLock rwl=new ReentrantReadWriteLock();//可重入读写锁  *****位置M*******
    public void processCachedData()//处理缓存的数据
    {
        Object data=null;//注意这里的data是线程私有的,而cacheMap是所有线程公用的
        //所以只需要考虑cacheMap的读写锁的问题,而不需要考虑data
        rwl.readLock().lock();//读锁上锁
        if(!this.cacheValid)//在缓存中并不存在     ********位置A********
        {
            //1首先必须释放读锁,因为接下来需要从其他地方读取数据并写入。读写锁是互斥的
            rwl.readLock().unlock();
            //2写锁上锁
            rwl.writeLock().lock();//位置获取写锁   ********位置B********
            //3再次检测是否在缓存中存在数据,原因是可能存在一个线程在当前线程执行到位置A与位置B之间的时候
            //获取了写锁,并写入数据将cachedValid状态改变
            if(!this.cacheValid){
                data=this.getData();//模拟从数据库或者文件系统等获取数据
                this.cacheValid=true;//将状态更改为缓存系统中已经存在该数据
            }
            //4 在释放写锁之前先进行降级 为了保证使用数据时,数据本身不被改变,需要读锁上锁,然后才释放写锁
            // ********此处设计小知识点:当前线程自己的读锁和写锁并不冲突******
            rwl.readLock().lock();//                       *****位置N*******
            //*********开始持有读锁***********************
            rwl.writeLock().unlock();//释放写锁
        }
        use(data);
        rwl.readLock().unlock();//释放读锁 在位置M、N处,读锁都进行了加锁所以这里需要将锁释放
    }
    public  Integer getData()
    {
        Integer a=new Random().nextInt(1000);
        return a;
    }
    public void use(Object data)//使用数据
    {
        System.out.println(data);
    }

    public static void main(String[] args) {

    }

}



什么是线程安全:在多线程访问的情况下,一个类总是能表现出正确的行为。

Lock提供比传统线程模型中的synchronized更加面向对象的方法,锁本身也是一个对象。两个线程的代码片段要实现同步互斥的效果,必须使用同一个Lock对象。锁要存放在要操作的资源的类的内部方法中,而不是线程代码

读写锁的定义:分为读锁和写锁,多个线程的读锁之间互相不互斥(只读不修改),读锁和写锁互斥,写锁和写锁互斥(相互修改)jvm自己控制,只要上好对应的锁即可。Jdk1.5提供的新功能与特性。

重点:当自己挂上读锁的时候仍然自己依然可以挂上写锁,但是其他线程不能挂上读锁,自己对自己是开放的。

  如果希望提高性能,需要多个线程可以同时读,而又相互之间不冲突。

Hibernate复习

缓存的代理:

  Useruser=session.load(id,User.class);返回的是一个User的代理对象,userProxy extends User

Eg: User$Proxy extends User{

     Private Integer id=id;

     User realUser=null;//保留了一个真正的User

  getName(){

    if(realUser==null)

{
     realUser=seesion.get(id);

    If(realUser==null)//对象为仍为空,则说明数据库中没有记录抛出异常

     Throwexception

      

}else

{

Return realUser.getName();

}

 

  Useruser=session.get(id,User.class);如果对象存在,则返回对象,不存在则返回null

面试题,设计一个缓存系统:

how to exploit reentrancy to perform lockdowngrading after updating a cache.

这是一个用来展示如何在更新缓存后利用可重入性执行锁定降级。

Exploit reentrancy 利用可重入性

Perform lock downgrading 执行锁定降级

Exception handling is elided for simplicity。

Exception handling 异常处理

Is elided 被忽略


你可能感兴趣的:(并发编程学习)