菜菜小杨 2022-01-24 14:12 采纳率: 100%
浏览 76
已结题

实例锁不是只有一把吗?为什么读写锁模式可以多线程同时调用含有synchronized的read方法?

最近在看java多线程设计模式时遇到如下问题 有点搞不懂了!问题:实例锁只有一把,而synchronized方法会获得实例对象的锁,下面程序是读写锁的线程,我不明白为什么实例锁只有一把,而读写锁可以多线程同时调用读方法,假设读者线程1调用Data中的read方法,进而调用了readLock方法,获得ReadWriteLock的实例锁,那么读者线程2为什么也可以调用这个synchronized限定的readlock方法,此时的锁不是给了线程1吗?线程2没有锁怎么去调用readlock方法呢?

img

 

public final class ReadWriteLock {
    private int readingReaders = 0; // (A)...实际正在读取的执行绪数量
    private int waitingWriters = 0; // (B)...正在等待写入的执行绪数量
    private int writingWriters = 0; // (C)...实际正在写入的执行绪数量
    private boolean preferWriter = true; // 写入优先的话,值为true

    public synchronized void readLock() throws InterruptedException {
        while (writingWriters > 0 || (preferWriter && waitingWriters > 0)) {
            wait();
        }
        readingReaders++;                       //  (A)实际正在读取的线程数量加1
    }

    public synchronized void readUnlock() {
        readingReaders--;                       //  (A)实际正在读取的线程数量减1
        preferWriter = true;
        notifyAll();
    }

    public synchronized void writeLock() throws InterruptedException {
        waitingWriters++;                       // (B)正在等待写入的线程数量加1
        try {
            while (readingReaders > 0 || writingWriters > 0) {
                wait();
            }
        } finally {1
          waitingWriters--;                   // (B)正在等待写入的线程数量减1
        }
        writingWriters++;                       //  (C)实际正在写入的线程数量加1
    }

    public synchronized void writeUnlock() {
        writingWriters--;                       // (C)实际正在写入的线程数量减
        preferWriter = false;
        notifyAll();
    }
}
// 数据类
public class Data {
    private final char[] buffer;
    private final ReadWriteLock lock = new ReadWriteLock();
    public Data(int size) {
        this.buffer = new char[size];
        for (int i = 0; i < buffer.length; i++) {
            buffer[i] = '*';
        }
    }
    public char[] read() throws InterruptedException {
        lock.readLock();
        try {
            return doRead();
        } finally {
            lock.readUnlock();
        }
    }
    public void write(char c) throws InterruptedException {
        lock.writeLock();
        try {
            doWrite(c);
        } finally {
            lock.writeUnlock();
        }
    }
    private char[] doRead() {
        char[] newbuf = new char[buffer.length];
        for (int i = 0; i < buffer.length; i++) {
            newbuf[i] = buffer[i];
        }
        slowly();
        return newbuf;
    }
    private void doWrite(char c) {
        for (int i = 0; i < buffer.length; i++) {
            buffer[i] = c;
            slowly();
        }
    }
    private void slowly() {
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
        }
    }
}

  • 写回答

2条回答 默认 最新

  • zcl_1991 2022-01-24 14:50
    关注

    这个 synchronized 不是给读写加锁,而是给获取读写锁前的操作加锁,获取到后 synchronized 就已经释放了,读写本身是没有锁的

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 2月2日
  • 已采纳回答 1月25日
  • 创建了问题 1月24日

悬赏问题

  • ¥15 metadata提取的PDF元数据,如何转换为一个Excel
  • ¥15 关于arduino编程toCharArray()函数的使用
  • ¥100 vc++混合CEF采用CLR方式编译报错
  • ¥15 coze 的插件输入飞书多维表格 app_token 后一直显示错误,如何解决?
  • ¥15 vite+vue3+plyr播放本地public文件夹下视频无法加载
  • ¥15 c#逐行读取txt文本,但是每一行里面数据之间空格数量不同
  • ¥50 如何openEuler 22.03上安装配置drbd
  • ¥20 ING91680C BLE5.3 芯片怎么实现串口收发数据
  • ¥15 无线连接树莓派,无法执行update,如何解决?(相关搜索:软件下载)
  • ¥15 Windows11, backspace, enter, space键失灵