Java中的读写锁Lock&ReadWriteLock

1、Java 中为了实现线程间互斥的效果,除了使用synchronized关键字外,还可以使用Lock对象去实现

public class LockTest
{
    //实例化Outputer对象
    static Outputer outputer = new Outputer();
    public static void main(String[] args)
    {
        //线程1
        Thread t1 = new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                while(true)
                {
                    //调用outputer对象的output
                    outputer.output("abcdefghijk");
                    try
                    {
                        Thread.sleep(10);
                    }
                    catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                }
            }
        });
        
        //线程2
        Thread t2 = new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                while(true)
                {
                    //调用outputer对象的output
                    outputer.output("mnopqrstuvw");
                    try
                    {
                        Thread.sleep(10);
                    }
                    catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                }
            }
        });
        
        t1.start();
        t2.start();
    }
}

class Outputer
{
    //生成当前对象的线程锁
    Lock lock = new ReentrantLock();
    public void output(String str)
    {
        lock.lock();
        try
        {
            int len = str.length();
            for(int i = 0; i < len; i++)
            {
                System.out.print(str.charAt(i));
            }
            
            System.out.println();
        }
        catch (Exception e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        finally
        {
            //释放对象锁
            lock.unlock();
        }
    }
}

使用lock或者是synchronized关键字,如果当前对象的锁,被其他线程获取,当前线程将无法执行被锁定的代码,那么如何实现 “执行读取操作不需要线程间互斥,仅写入操作才实现互斥”

2、Java中的ReadWriteLock对象的使用

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

public class ReadWriteLockTest
{
    public static void main(String[] args)
    {
        final MyQueue queue = new MyQueue();
        for(int i = 0; i < 3; i++)
        {
            new Thread(new Runnable()
            {
                @Override
                public void run()
                {
                    while (true)
                    {
                        queue.get();
                    }
                }
            }).start();
        }
        
        for(int i = 0; i < 3; i++)
        {
            new Thread(new Runnable()
            {
                @Override
                public void run()
                {
                    while (true)
                    {
                        queue.set(new Random().nextInt(10000));
                    }
                }
            }).start();
        }
    }
}

class MyQueue
{
    /*
     * 共享数据
     * 只能有一个线程对此数据执行写操作
     * 可以有多个线程对此线程执行读操作
     */
    private Object data = null;
    
    //读写锁
    private ReadWriteLock lock = new ReentrantReadWriteLock();
    
    public void get()
    {
        //lock
        lock.readLock().lock();
        try
        {
            System.out.println(Thread.currentThread().getName()
                    + " 准备读取数据!");
            Thread.sleep((long)new Random().nextInt(1000));
            System.out.println(Thread.currentThread().getName() + 
                    " 数据读取完成  data = " + data);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        finally
        {
            //unlock
            lock.readLock().unlock();
        }
        
    }
    
    public void set(Object data)
    {
        //lock
        lock.writeLock().lock();
        try
        {
            System.out.println(Thread.currentThread().getName()
                    + " 准备写入数据!");
            Thread.sleep((long)new Random().nextInt(1000));
            this.data = data;
            
            System.out.println(Thread.currentThread().getName()
                    + " 写入数据完成  data = " + data);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        finally
        {
            //lock
            lock.writeLock().unlock();
        }
    }
}


关于ReadWriteLocak对象实现读写锁的面试题:写出一份缓存系统的伪代码

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

public class CacheDemo
{
    //cacheMap用于保存已经获取的对象数据
    private Map<String, Object> cacheMap = 
        new HashMap<String, Object>();
    //读写锁
    private ReadWriteLock lock = new ReentrantReadWriteLock();
    
    /**
     * 获取数据
     * @param key
     * @return Object
     */
    public Object getData(String key)
    {
        /*
         * 读取数据锁 上锁
         * 是为了保证多个线程读取数据的时,不会产生空数据
         */
        lock.readLock().lock();
        Object obj = null;
        try
        {
            //从缓存区中获取数据
            obj = cacheMap.get(key);
            //判断是否存在数据 如果不存在数据则创建新数据
            if(obj == null)
            {
                //释放读取数据锁 P1
                lock.readLock().unlock();
                //获取写数据锁 P2
                lock.writeLock().lock();
                
                /*
                 * 由于读数据锁可以多个线程同时读取 
                 * 因为可能有多个线程处于P1位置或者出去P2等待写锁的位置
                 * 为了避免多次执行写操作
                 * 所以在获得写锁后 再次判断是否为空
                 */
                if(obj == null || cacheMap.get(key) == null)
                {
                    try
                    {
                        //创建新的数据
                        obj = new Object();
                        //将数据放入缓存区中
                        cacheMap.put(key, obj);
                    }
                    catch (Exception e)
                    {
                        e.printStackTrace();
                    }
                }
                
                //获取读取锁
                lock.readLock().lock();
                //释放写数据锁
                lock.writeLock().unlock();
            }
        }
        catch (Exception e) 
        {
            e.printStackTrace();
        }

        //释放读取数据锁
        lock.readLock().unlock();
        return obj;
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值