Java多线程(八):ReentrantReadWriteLock

读写锁ReentrantReadWriteLock概述

读写锁ReentrantReadWriteLock,使用它比ReentrantLock效率更高。java

读写锁表示两个锁,一个是读操做相关的锁,称为共享锁;另外一个是写操做相关的锁,称为排他锁。安全

一、读和读之间不互斥,由于读操做不会有线程安全问题线程

二、写和写之间互斥,避免一个写操做影响另一个写操做,引起线程安全问题code

三、读和写之间互斥,避免读操做的时候写操做修改了内容,引起线程安全问题get

多个Thread能够同时进行读取操做,可是同一时刻只容许一个Thread进行写入操做。it

读操做和读操做共享

请看例子
ThreadDomain44类和main方法io

public class ThreadDomain44 extends ReentrantReadWriteLock
{
    public void read()
    {
        try
        {
            readLock().lock();
            System.out.println(Thread.currentThread().getName() + "得到了读锁, 时间为" +
                    System.currentTimeMillis());
            Thread.sleep(10000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        finally
        {
            readLock().unlock();
        }
    }

    public static void main(String[] args)
    {
        final ThreadDomain44 td = new ThreadDomain44();
        Runnable readRunnable = new Runnable()
        {
            public void run()
            {
                td.read();
            }
        };
        Thread t0 = new Thread(readRunnable);
        Thread t1 = new Thread(readRunnable);
        t0.start();
        t1.start();
    }
}

输出结果以下class

Thread-0得到了读锁, 时间为1564018325618
Thread-1得到了读锁, 时间为1564018325618

尽管加了Thread.sleep(10000);两个线程几乎同时执行lock()后面的方法。说明readLock().lock()容许多个线程执行而且能提升执行效率。效率

写操做和写操做互斥

请看例子方法

public class ThreadDomain45 extends ReentrantReadWriteLock {
    public void write()
    {
        try
        {
            writeLock().lock();
            System.out.println(Thread.currentThread().getName() + "得到了写锁, 时间为" +
                    new Date());
            Thread.sleep(10000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        finally
        {
            writeLock().unlock();
        }
    }

    public static void main(String[] args)
    {
        final ThreadDomain45 td = new ThreadDomain45();
        Runnable readRunnable = new Runnable()
        {
            public void run()
            {
                td.write();
            }
        };
        Thread t0 = new Thread(readRunnable);
        Thread t1 = new Thread(readRunnable);
        t0.start();
        t1.start();
    }
}

输出结果

Thread-1得到了写锁, 时间为Tue Jul 30 11:26:21 CST 2019
Thread-0得到了写锁, 时间为Tue Jul 30 11:26:31 CST 2019

能够看到,后得到锁的Thread-0等待了十秒,说明写和写互斥

读操做和写操做互斥/写操做和读操做互斥

例子以下

public class ThreadDomain46 extends ReentrantReadWriteLock {
    public void write()
    {
        try
        {
            writeLock().lock();
            System.out.println(Thread.currentThread().getName() + "得到了写锁, 时间为" +
                    new Date());
            Thread.sleep(10000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        finally
        {
            writeLock().unlock();
        }
    }

    public void read()
    {
        try
        {
            readLock().lock();
            System.out.println(Thread.currentThread().getName() + "得到了读锁, 时间为" +
                    new Date());
            Thread.sleep(10000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        finally
        {
            readLock().unlock();
        }
    }

    public static void main(String[] args)
    {
        final ThreadDomain46 td = new ThreadDomain46();
        Runnable readRunnable = new Runnable()
        {
            public void run()
            {
                td.read();
            }
        };
        Runnable writeRunnable = new Runnable()
        {
            public void run()
            {
                td.write();
            }
        };
        Thread t0 = new Thread(readRunnable);
        Thread t1 = new Thread(writeRunnable);
        t0.start();
        t1.start();
    }
}

输出结果以下

Thread-0得到了读锁, 时间为Tue Jul 30 11:49:15 CST 2019
Thread-1得到了写锁, 时间为Tue Jul 30 11:49:26 CST 2019

能够看到Thread-0得到读锁执行完10s后Thread-1才得到了写锁,说明读操做和写操做互斥。
另外一种输出结果以下

Thread-1得到了写锁, 时间为Tue Jul 30 14:14:07 CST 2019
Thread-0得到了读锁, 时间为Tue Jul 30 14:14:17 CST 2019

能够看到Thread-1得到写锁执行完10s后Thread-0才得到了读锁,说明写操做和读操做互斥。

相关文章
相关标签/搜索