读写锁

1.什么是读写锁

读写锁就是对共享资源既可以加读锁,也可以加写锁,而不是简单的独占锁。当没有对共享资源加写锁时,多个线程都可以申请读锁,但是只能有一个线程加写锁;当对共享资源加了写锁后,其他线程不能加读锁和写锁。写锁是独占锁,读锁是共享锁。

2.读写锁的简单实现

package lock;

import sun.misc.Unsafe;

import java.lang.reflect.Field;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReadWriteLock;

/**
 * 读写锁,如果没有写锁,都可以加读锁,只能一个线程加写锁;如果有写锁,
 *
 *
 */
public class MyReadWriteLock implements ReadWriteLock {

    /**
     * 写锁标识,0-无写锁,1-申请写锁,2-有写锁
     */
    private volatile int writeFlag;

    private final ReadLock readLock;

    private final WriteLock writeLock;

    private final Sync sync = new Sync();

    public MyReadWriteLock() {
        this.readLock = new ReadLock();
        this.writeLock = new WriteLock();
    }

    public boolean isWrite() {
        return writeFlag > 0;
    }

    public int getWriteFlag() {
        return writeFlag;
    }

    public void compareAndSetWriteFlag(int expect, int update) {
        unsafe.compareAndSwapInt(this, writeFlagOffset, expect, update);
    }

    public Sync getSync() {
        return sync;
    }

    class Sync extends AbstractQueuedSynchronizer {

        @Override
        protected int tryAcquireShared(int arg) {
            int c = getState();
            if (getWriteFlag() > 0 && getExclusiveOwnerThread() != Thread.currentThread()) {//正在申请写锁或者已加写锁,不能再加读锁
                return -1;
            }
            compareAndSetState(getState(), getState() + 1);
            return 1;
        }

        @Override
        protected boolean tryReleaseShared(int arg) {
            return compareAndSetState(getState(), getState() - 1);
        }

        @Override
        protected boolean tryAcquire(int arg) {
            if (getWriteFlag() > 0 || getState() > 0) {//已加写锁或读锁,不能加写锁,得等待读锁或者写锁释放
                return false;
            }
            compareAndSetWriteFlag(getWriteFlag(), getWriteFlag() + 1);
            setExclusiveOwnerThread(Thread.currentThread());
            return true;
        }

        @Override
        protected boolean tryRelease(int arg) {
            compareAndSetWriteFlag(getWriteFlag(), getWriteFlag() - 1);
            setExclusiveOwnerThread(null);
            return true;
        }
    }

    /**
     * 读锁
     */
    class ReadLock implements java.util.concurrent.locks.Lock {

        final Sync sync;

        public ReadLock() {
            sync = getSync();
        }

        @Override
        public void lock() {
            sync.acquireShared(1);
        }

        @Override
        public void lockInterruptibly() throws InterruptedException {

        }

        @Override
        public boolean tryLock() {
            return false;
        }

        @Override
        public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
            return false;
        }

        @Override
        public void unlock() {
            sync.releaseShared(1);
        }

        @Override
        public Condition newCondition() {
            return null;
        }
    }

    class WriteLock implements java.util.concurrent.locks.Lock {

        final Sync sync;

        public WriteLock() {
            this.sync = getSync();
        }

        @Override
        public void lock() {
            sync.acquire(1);
        }

        @Override
        public void lockInterruptibly() throws InterruptedException {

        }

        @Override
        public boolean tryLock() {
            return false;
        }

        @Override
        public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
            return false;
        }

        @Override
        public void unlock() {
            sync.release(1);
        }

        @Override
        public Condition newCondition() {
            return null;
        }
    }

    /**
     * 加读锁
     */
    public java.util.concurrent.locks.Lock readLock() {
        return readLock;
    }

    /**
     * 加写锁
     */
    public java.util.concurrent.locks.Lock writeLock() {
        return writeLock;
    }

    private static final Unsafe unsafe;
    private static final long writeFlagOffset;

    static {
        try {
            Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafeInstance.setAccessible(true);
           unsafe =  (Unsafe) theUnsafeInstance.get(Unsafe.class);
            writeFlagOffset = unsafe.objectFieldOffset(MyReadWriteLock.class.getDeclaredField("writeFlag"));
        } catch (Exception e) {
            throw new Error(e);
        }
    }

}

3.示例

import lock.MyReadWriteLock;

/**
 * 场景描述:网上图书馆里的书只能管理员进行修改,读者只能读。
 * 10个读者可以同时读同一本书,但是管理员修改书的时候任何人都不能读
 */
public class TestMyReadWriteLock {

    private static final MyReadWriteLock lock = new MyReadWriteLock();

    public static void main(String[] args) {
        for (int i = 0 ; i < 10 ; i++) {
           new Thread(new Reader(i+1)).start();
        }
        new Thread(new Manager("管理员")).start();
    }

    /**
     * 管理员线程
     */
    static class Manager implements Runnable {

        private String name;

        public Manager(String name) {
            this.name = name;
        }

        @Override
        public void run() {
            Thread.currentThread().setName(name);
            while (true) {
                lock.writeLock().lock();
                System.out.println(Thread.currentThread().getName() +"加写锁成功,可以进行写操作");
                System.out.println(Thread.currentThread().getName() +"正在进行写操作。。。。。");
                try {
                    Thread.sleep(10*1000);
                } catch (InterruptedException e) {
                    System.out.println(Thread.currentThread().getName() +"写操作异常");
                    lock.writeLock().unlock();
                }
                System.out.println(Thread.currentThread().getName() +"写操作完毕,释放写锁");
                lock.writeLock().unlock();
                //隔一段时间再进行写操作
                try {
                    Thread.sleep(30*1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 读者
     */
    static class Reader implements Runnable {

        /**
         * 隔一段时间再去读书
         */
        private long readTime;

        public Reader(long readTime) {
            this.readTime = readTime;
        }

        @Override
        public void run() {
            while (true) {
                lock.readLock().lock();
                System.out.println(Thread.currentThread().getName() + "加读锁成功,可以进行读操作");
                System.out.println(Thread.currentThread().getName() +"正在进行读操作。。。。。");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    System.out.println(Thread.currentThread().getName() +"读操作异常,释放本身持有的读锁");
                    lock.readLock().unlock();
                }
                System.out.println(Thread.currentThread().getName() +"读操作完毕,释放本身持有的读锁");
                lock.readLock().unlock();
                //隔一段时间再进行写操作
                try {
                    Thread.sleep(readTime * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

友情链接更多精彩内容