读写分离锁的简单实现

背景

当多线程访问共享数据时,为保证线程安全,通常情况下会对共享数据加锁。最简单的方式在读或者写共享数据时加锁。但是这样会影响到效率。比如,多个线程只对数据做读操作而没有其他线程对其写操作时,读线程没有必要被阻塞,这时不存在线程安全问题。
总结一下

是否加锁readwrite
readFT
writeTT

也就是说,当只有度线程时,才无需加锁。

首先定义锁

public class ReadWriteLock {
    private int readingReaders = 0;
    private int waitingReaders = 0;
    private int writingWriters = 0;
    private int waitingWriters = 0;

    public synchronized void readLock() throws InterruptedException {
        waitingReaders++;
        try {
            while (writingWriters > 0) {
                this.wait();
            }
            readingReaders++;
        } finally {
            waitingReaders--;
        }

    }

    public synchronized void readUnlock() {
        readingReaders--;
        this.notifyAll();
    }

    public synchronized void writeLock() throws InterruptedException {
        waitingWriters++;
        try {
            while (readingReaders > 0 || writingWriters > 0) {
                this.wait();
            }
            writingWriters++;
        } finally {
            waitingWriters--;
        }

    }

    public synchronized void writeUnlock() {
        writingWriters--;
        this.notifyAll();
    }

}

首先定义四个变量,用于计数当前读写,等待读写的线程数量

    private int readingReaders = 0;
    private int waitingReaders = 0;
    private int writeWriters = 0;
    private int waitingWriters = 0;

根据表格,读线程等待的条件是有活跃的读线程,因此

public synchronized void readLock() throws InterruptedException {
        waitingReaders++;
        try {
            while (writingWriters > 0) {
                this.wait();
            }
            readingReaders++;
        } finally {
            waitingReaders--;
        }

    }

只判断writeWriters是否大于0.

同理,写锁是否wait的条件,是当前有线程正在读数据或者当前有线程在写数据

public synchronized void writeLock() throws InterruptedException {
        waitingWriters++;
        try {
            while (readingReaders > 0 || waitingWriters > 0) {
                this.wait();
            }
            writingWriters++;
        } finally {
            waitingWriters--;
        }

    }

这样,一个读写分离锁便定义好了。现在定义共享资源,模拟读写

public class SharedData {
    private char[] data = new char[10];

    public SharedData(char c) {
        for (int i = 0; i < data.length; i++) {
            data[i] = c;
        }
    }

    public String readData() {
        StringBuffer s = new StringBuffer();
        for (int i = 0; i < data.length; i++) {
            s.append(data[i]);
        }
        return s.toString();
    }

    public void writeData(char c) {
    System.out.println(Thread.currentThread().getName() + " write date char[" + c + "]");
        for (int i = 0; i < data.length; i++) {
            data[i] = c;
        }
    }


}

测试类

public class ReadWriteLockTest {
    public static void main(String[] args) {
        ReadWriteLock lock = new ReadWriteLock();
        SharedData data = new SharedData('*');

        IntStream.range(0, 10).forEach(i -> {
            Thread t = new Thread(() -> {
                try {
                    while (true) {
                        lock.readLock();
                        System.out.println(Thread.currentThread().getName() + " " + data.readData());
                        lock.readUnlock();
                        Thread.sleep(10);
                    }

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }, "Thread read" + i);
            t.start();
        });

        IntStream.range(0, 10).forEach(i -> {
            Thread t = new Thread(() -> {
                try {
                    while (true) {
                        lock.writeLock();
                        data.writeData(randomChar());
                        lock.writeUnlock();
                        Thread.sleep(10);
                    }

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }, "Thread write" + i);
            t.start();
        });
    }

    private synchronized static char randomChar() {
        Random r = new Random();
        int i = r.nextInt(10);
        return (char) (i + 118);
    }
}

结果

Thread read0 **********
Thread read4 **********
Thread read3 **********
Thread read2 **********
Thread read1 **********
Thread read6 **********
Thread read5 **********
Thread read7 **********
Thread read8 **********
Thread read9 **********
Thread write0 write date char[}]
Thread write5 write date char[v]
Thread write1 write date char[y]
Thread write4 write date char[]
Thread write6 write date char[~]
Thread write3 write date char[z]
Thread write2 write date char[v]
Thread write8 write date char[|]
Thread write9 write date char[z]
Thread write7 write date char[v]
Thread read4 vvvvvvvvvv
Thread read1 vvvvvvvvvv
Thread read7 vvvvvvvvvv
Thread read3 vvvvvvvvvv
Thread read0 vvvvvvvvvv
Thread read6 vvvvvvvvvv
Thread read2 vvvvvvvvvv
Thread write4 write date char[{]
Thread write2 write date char[y]
Thread read8 yyyyyyyyyy
Thread read9 yyyyyyyyyy
Thread read5 yyyyyyyyyy
Thread write5 write date char[v]
Thread write0 write date char[v]
Thread write1 write date char[v]
Thread write7 write date char[~]
Thread write9 write date char[w]
Thread write8 write date char[}]
Thread write6 write date char[v]
Thread write3 write date char[~]
Thread read1 ~~~~~~~~~~
Thread read7 ~~~~~~~~~~
Thread read3 ~~~~~~~~~~
Thread read4 ~~~~~~~~~~
Thread read6 ~~~~~~~~~~
Thread read2 ~~~~~~~~~~
Thread read8 ~~~~~~~~~~
Thread read0 ~~~~~~~~~~
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值