Java 可重入写回。读写获取优先级

Java 可重入写回。读写获取优先级,java,multithreading,concurrency,locking,reentrantreadwritelock,Java,Multithreading,Concurrency,Locking,Reentrantreadwritelock,我研究可重入式写锁 java文档中的代码片段: 在最早的一次读取之后,线程才会获取读取锁 当前等待写入线程已获取并释放写入 锁 正如我所理解的那样 读取持续时间-1时间单位 写入持续时间-3时间单位 时间0-已获取写入锁 时间1-读取锁定尝试读取 时间2- 写锁试写 因此,我期望以下顺序: 首笔 第二次写入 阅读 我的实验代码: public class RWLockCalculator { static long initTime = System.currentTimeMillis(

我研究可重入式写锁

java文档中的代码片段:

在最早的一次读取之后,线程才会获取读取锁 当前等待写入线程已获取并释放写入 锁

正如我所理解的那样

读取持续时间-1时间单位

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

  • 时间0-已获取写入锁
  • 时间1-读取锁定尝试读取
  • 时间2- 写锁试写
  • 因此,我期望以下顺序:

  • 首笔
  • 第二次写入
  • 阅读
  • 我的实验代码:

    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));
        }
    }
    
    输出:

    因此我得到

  • 首笔
  • 阅读
  • 第二次写入
  • 为什么我会得到这个结果


    是否可能中断FIFO顺序

    更新 请比较java文档中的两个兄弟片段(关于公平模式):

    首先

    尝试获取公平读取锁(非可重入)的线程将在写入锁被持有或存在等待写入线程时阻塞。在当前等待的最旧写入线程获取并释放写锁之前,该线程不会获取读锁。当然,如果等待的写入程序放弃等待,将一个或多个读卡器线程作为队列中最长的等待程序保留写锁,则这些读卡器将被分配读锁。

    第二:

    尝试获取公平写锁(非可重入)的线程将阻塞,除非读锁和写锁都是空闲的(这意味着没有等待的线程)。(请注意,非阻塞的ReentrantReadWriteLock.ReadLock.tryLock()和ReentrantReadWriteLock.WriteLock.tryLock()方法不支持此公平设置,并且将在可能的情况下获取锁,而不考虑等待的线程。)

    我不完全理解其中所写内容的含义,但我看到,
    ReentrantReadWriteLock
    使用不同的策略获取读锁和写锁。我建议,如果政治在Javadoc中是一样的,就不会写两个缩进


    ReadLock可以共享锁。这仅仅是一个区别吗?

    首先,应在公平模式下创建可重入的写锁,以强制特定的锁获取顺序:

    private static ReadWriteLock lock = new ReentrantReadWriteLock(true);
    
    然后,非常清楚地描述了您的案例:

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


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

    我认为“当前等待的最早的写卡器线程”是读卡器线程请求锁时的线程。因此,在你的例子中,没有等待的作者,读者是下一个。@SpaceTrucker,这公平吗?FIFO?是否可能中断FIFO顺序?所有线程都位于公共队列中。无论是写锁还是读锁,它都希望获得?Яаааааааааааааа。Получается, что всё равно какой лок(на чтение или на запись) ждёт поток - все они стоят в очереди. 读取和写入锁定策略必须不同,因为写入锁定是独占的,而读取锁定不是独占的。据我所知,它本质上充当写入线程和读线程组(可能共享锁)的FIFO队列。
    private static ReadWriteLock lock = new ReentrantReadWriteLock(true);