首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >ReentrantReadWriteLock。读写优先

ReentrantReadWriteLock。读写优先
EN

Stack Overflow用户
提问于 2014-04-16 08:32:01
回答 1查看 2.1K关注 0票数 3

我研究ReentrantReadWriteLock

来自java文档的代码片段:

在当前最老的等待写入线程获得并释放写锁之前,线程将不会获取读锁。

正如我所理解的那样。

读取时间-1时间单位

写入持续时间-3时间单元

  1. 时间0-获得写入锁
  2. 时间1-读锁试读
  3. 时间2-写锁尝试写

因此,我期望以下顺序:

  1. 第一写
  2. 第二写
  3. 朗读

我的实验代码:

代码语言:javascript
复制
public class RWLockCalculator {
    static long initTime = System.currentTimeMillis();
    private static int calculatedValue = 0;
    private static ReadWriteLock lock = new ReentrantReadWriteLock();
    public void calculate(int value) {
        lock.writeLock().lock();
        try {           
            System.out.println("write lock acquired at "+ (System.currentTimeMillis()-RWLockCalculator.initTime));
            this.calculatedValue = 1;
            Thread.sleep(300);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            lock.writeLock().unlock();
        }
    }

    public int getCalculatedValue() {
        lock.readLock().lock();
        try {           
            System.out.println("read lock acquired at "+ (System.currentTimeMillis()-RWLockCalculator.initTime));
            Thread.sleep(100);
            return calculatedValue;
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return -1;
        } finally {
            lock.readLock().unlock();
        }
    }
}

class Test {
    public static void main(String[] args) throws InterruptedException {
        new WriteThread().start();
        Thread.sleep(100);
        new ReadThread().start();
        Thread.sleep(100);
        new WriteThread().start();

    }
}

class ReadThread extends Thread {
    @Override
    public void run() {
        System.out.println(new RWLockCalculator().getCalculatedValue() + ", " + (System.currentTimeMillis() - RWLockCalculator.initTime));
    }
}

class WriteThread extends Thread {
    @Override
    public void run() {
        new RWLockCalculator().calculate(99);
        System.out.println("I have written in  " + (System.currentTimeMillis() - RWLockCalculator.initTime));
    }
}

退出:

代码语言:javascript
复制
write lock acquired at 0
I have written in  300
read lock acquired at 300
1, 400
write lock acquired at 400
I have written in  700

所以我得到了

  1. 第一写
  2. 朗读
  3. 第二写

我为什么要得到这个结果?

有可能打破FIFO的顺序吗?

更新

请比较来自java的两个兄弟级代码段(关于公平模式):

第一

一个试图获得公平读锁(非真实地)的线程,如果持有写锁,或者存在等待写入线程,则会阻塞。在当前最老的等待写入线程获得并释放写入锁之前,线程将不会获取读锁。当然,如果等待的写入器放弃等待,留下一个或多个读取器线程作为队列中最长的等待者,并且没有写入锁,那么这些读取器将被分配读锁。

第二:

一个线程试图获得一个公平的写锁(非真实地)将阻塞,除非读锁和写锁都是空闲的(这意味着没有等待的线程)。(请注意,非阻塞的ReentrantReadWriteLock.ReadLock.tryLock()和ReentrantReadWriteLock.WriteLock.tryLock()方法不符合此公平设置,如果可能的话将获取锁,无论等待线程如何。)

我不完全理解在那里写什么的意思,但是我看到ReentrantReadWriteLock使用不同的策略来获得读锁和写锁。我建议,如果在java中政治是一样的,doc不会写两个缩进。

ReadLock可以共享锁。只有一个不同吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-04-16 09:34:16

首先,应该以公平的方式创建ReentrantReadWriteLock,以强制执行特定的锁获取顺序:

代码语言:javascript
复制
private static ReadWriteLock lock = new ReentrantReadWriteLock(true);

然后,javadoc非常清楚地描述了您的情况:

当以公平的方式构造时,线程会使用一个近似到达顺序的策略来争夺条目.当当前持有的锁释放时,将为等待时间最长的单个写入线程分配写锁,或者如果有一组读取器线程等待时间超过所有等待的写入线程,则该组将被分配读锁。

由于您的读者线程等待的时间比第二个写入线程长,因此它在写入线程之前获得一个锁。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23104012

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档