3

Java doc: ReentrantReadWriteLockを読みました

そして、writeLock が readLock よりも優先されることはわかりません

しかし、次のようなトピックも読みました: ReentrantReadWriteLock の読み取りロックと書き込みロックは何らかの関連がありますか?
そして、次のフレーズの両方の回答に表示されます。

ロックがリーダーによって保持され、スレッドが書き込みロックを要求した場合、書き込みロックを取得したスレッドがそれを解放するまで、リーダーは読み取りロックを取得できません。


読者よりも作家を好む。つまり、ライターがロックを待機している場合、他のスレッドからの新しいリーダーはリソースにアクセスできません。既存のリーダーは、ロックを解除するまで引き続きリソースを使用できます。これにより、いわゆる「ライターの飢餓」が防止されます。

そして、これらのフレーズは意味があり、どこかですでに読んだようです。

しかし、明らかにそれは Java doc と矛盾しています。

最新のJDKで変更されましたか? それはまだ有効ですか?

ライターの飢餓を防ぐには?

4

3 に答える 3

2

確認するサンプルを作成しました:

public class RWLockTest {
    public static final Logger LOGGER = LoggerFactory.getLogger(RWLockTest.class);

       public static void main(String[] args) {
        SomeClass someClass = new SomeClass();

        Reader readerRunnable = new Reader(someClass);
        Writer writerRunnable = new Writer(someClass);
        //group 1 readers
        for (int i = 0; i < 10; i++) {
            new Thread(readerRunnable).start();
        }

        // 2 writers
        new Thread(writerRunnable).start();
        LOGGER.info("!!!!!!!!!!!!!!!WRITER_1 WAS STARTED!!!!!!!!!!!!!!!");
        new Thread(writerRunnable).start();
        LOGGER.info("!!!!!!!!!!!!!!!WRITER_2 WAS STARTED!!!!!!!!!!!!!!!");

       //group 2 readers            
       for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(readerRunnable);
            LOGGER.info(String.format("%s was submitted", thread.getId()));
            thread.start();
        }
    }

    public static class SomeClass {
        public ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

        public void read() {
            readWriteLock.readLock().lock();
            try {
                LOGGER.info(String.format("Read by %s started", Thread.currentThread().getId()));
                Thread.sleep(5000);
                LOGGER.info(String.format("Read by %s finished", Thread.currentThread().getId()));
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                readWriteLock.readLock().unlock();

            }
        }

        public void write() {
            readWriteLock.writeLock().lock();
            try {
                LOGGER.info(String.format("!!!!!!!!!!Write by %s started!!!!!!!!!!!!", Thread.currentThread().getId()));
                Thread.sleep(3000);
                LOGGER.info(String.format("!!!!!!!!!!Write by %s finished!!!!!!!!", Thread.currentThread().getId()));
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                readWriteLock.writeLock().unlock();

            }
        }

    }

    public static class Reader implements Runnable {
        SomeClass someClass;

        public Reader(SomeClass someClass) {
            this.someClass = someClass;
        }

        @Override
        public void run() {
            someClass.read();
        }
    }

    public static class Writer implements Runnable {
        SomeClass someClass;

        public Writer(SomeClass someClass) {
            this.someClass = someClass;
        }

        @Override
        public void run() {
            someClass.write();
        }
    }
}

私は多くの時間を実行しようとしましたが、通常、出力は次のようになります。

16:31:49.037 [main] INFO my.pack.RWLockTest - !!!!!!!!!!!!!!!WRITER_1 WAS STARTED!!!!!!!!!!!!!!!
16:31:49.040 [main] INFO my.pack.RWLockTest - !!!!!!!!!!!!!!!WRITER_2 WAS STARTED!!!!!!!!!!!!!!!
16:31:49.046 [Thread-1] INFO my.pack.RWLockTest - Read by 13 started
16:31:49.046 [main] INFO my.pack.RWLockTest - 24 was submitted
16:31:49.046 [Thread-7] INFO my.pack.RWLockTest - Read by 19 started
16:31:49.046 [Thread-4] INFO my.pack.RWLockTest - Read by 16 started
16:31:49.046 [Thread-5] INFO my.pack.RWLockTest - Read by 17 started
16:31:49.046 [Thread-0] INFO my.pack.RWLockTest - Read by 12 started
16:31:49.046 [Thread-3] INFO my.pack.RWLockTest - Read by 15 started
16:31:49.047 [main] INFO my.pack.RWLockTest - 25 was submitted
16:31:49.046 [Thread-9] INFO my.pack.RWLockTest - Read by 21 started
16:31:49.047 [Thread-8] INFO my.pack.RWLockTest - Read by 20 started
16:31:49.047 [main] INFO my.pack.RWLockTest - 26 was submitted
16:31:49.047 [Thread-2] INFO my.pack.RWLockTest - Read by 14 started
16:31:49.047 [Thread-6] INFO my.pack.RWLockTest - Read by 18 started
16:31:49.047 [main] INFO my.pack.RWLockTest - 27 was submitted
16:31:49.048 [main] INFO my.pack.RWLockTest - 28 was submitted
16:31:49.048 [main] INFO my.pack.RWLockTest - 29 was submitted
16:31:49.048 [main] INFO my.pack.RWLockTest - 30 was submitted
16:31:49.048 [main] INFO my.pack.RWLockTest - 31 was submitted
16:31:49.049 [main] INFO my.pack.RWLockTest - 32 was submitted
16:31:49.049 [main] INFO my.pack.RWLockTest - 33 was submitted
16:31:54.047 [Thread-7] INFO my.pack.RWLockTest - Read by 19 finished
16:31:54.048 [Thread-6] INFO my.pack.RWLockTest - Read by 18 finished
16:31:54.047 [Thread-5] INFO my.pack.RWLockTest - Read by 17 finished
16:31:54.049 [Thread-2] INFO my.pack.RWLockTest - Read by 14 finished
16:31:54.051 [Thread-8] INFO my.pack.RWLockTest - Read by 20 finished
16:31:54.047 [Thread-1] INFO my.pack.RWLockTest - Read by 13 finished
16:31:54.050 [Thread-9] INFO my.pack.RWLockTest - Read by 21 finished
16:31:54.049 [Thread-4] INFO my.pack.RWLockTest - Read by 16 finished
16:31:54.049 [Thread-3] INFO my.pack.RWLockTest - Read by 15 finished
16:31:54.049 [Thread-0] INFO my.pack.RWLockTest - Read by 12 finished
16:31:54.057 [Thread-10] INFO my.pack.RWLockTest - !!!!!!!!!!Write by 22 started!!!!!!!!!!!!
16:31:57.057 [Thread-10] INFO my.pack.RWLockTest - !!!!!!!!!!Write by 22 finished!!!!!!!!
16:31:57.058 [Thread-11] INFO my.pack.RWLockTest - !!!!!!!!!!Write by 23 started!!!!!!!!!!!!
16:32:00.060 [Thread-11] INFO my.pack.RWLockTest - !!!!!!!!!!Write by 23 finished!!!!!!!!
16:32:00.061 [Thread-13] INFO my.pack.RWLockTest - Read by 25 started
16:32:00.061 [Thread-14] INFO my.pack.RWLockTest - Read by 26 started
16:32:00.061 [Thread-12] INFO my.pack.RWLockTest - Read by 24 started
16:32:00.061 [Thread-15] INFO my.pack.RWLockTest - Read by 27 started
16:32:00.061 [Thread-17] INFO my.pack.RWLockTest - Read by 29 started
16:32:00.062 [Thread-19] INFO my.pack.RWLockTest - Read by 31 started
16:32:00.062 [Thread-18] INFO my.pack.RWLockTest - Read by 30 started
16:32:00.061 [Thread-16] INFO my.pack.RWLockTest - Read by 28 started
16:32:00.062 [Thread-20] INFO my.pack.RWLockTest - Read by 32 started
16:32:00.062 [Thread-21] INFO my.pack.RWLockTest - Read by 33 started
16:32:05.060 [Thread-12] INFO my.pack.RWLockTest - Read by 24 finished
16:32:05.060 [Thread-15] INFO my.pack.RWLockTest - Read by 27 finished
16:32:05.060 [Thread-13] INFO my.pack.RWLockTest - Read by 25 finished
16:32:05.060 [Thread-17] INFO my.pack.RWLockTest - Read by 29 finished
16:32:05.060 [Thread-14] INFO my.pack.RWLockTest - Read by 26 finished
16:32:05.062 [Thread-21] INFO my.pack.RWLockTest - Read by 33 finished
16:32:05.062 [Thread-16] INFO my.pack.RWLockTest - Read by 28 finished
16:32:05.062 [Thread-19] INFO my.pack.RWLockTest - Read by 31 finished
16:32:05.062 [Thread-18] INFO my.pack.RWLockTest - Read by 30 finished
16:32:05.062 [Thread-20] INFO my.pack.RWLockTest - Read by 32 finished

どういう意味ですか?

ご覧のとおり、次のことを行います。

  1. 読み取り用に 10 個のスレッドを実行します。10 個のスレッドすべてが並行して動作できます。各読み取りには 5 秒かかります
  2. 次に、2 つのライターを開始します (1 つの書き込みには 3 秒かかります)。
  3. それから私は10人の読者を始めます

ご覧のとおり、最初の書き込みが送信されてから ( 16:31:49.037 [main] INFO my.pack.RWLockTest - !!!!!!!!!!!!!!!WRITER_1 WAS STARTED!!!!!!!!!!!!!!!)、実際に指定された ((ロックを取得) 16:31:54.057 [Thread-10] INFO my.pack.RWLockTest - !!!!!!!!!!Write by 22 started!!!!!!!!!!!!) までの遅延は 5 秒です。読書の時間です。

また、2 つのライター スレッドが送信された後、IDが 24 から 33の 10 個のリーダー スレッドが送信され、ライター スレッドが作業を終了した後、それらすべてが実際に開始された (ロックを取得した) ことがわかります。

そのため、IDが 24 から 33のリーダー スレッドが に送信され16:31:49、この時点で最初の 10 人のリーダーが読み取りロックを取得し、それらも読み取りロックを取得できたように見えますがReentrantReadWriteLock、ライターの飢餓を回避するために内部に何かがあるようです。最終的に、リーダーの 2 番目のグループは16:32:00(送信後 6 秒)でのみロックを取得できました。

保証されているかどうかはわかりませんが、私のテストでは、常にそのように機能します。そのため、Java docには次のように書かれていますが、リーダーよりもライターを優先しています。

このクラスは、ロック アクセスに対してリーダーまたはライターの優先順位を課しません。

于 2019-10-17T13:48:23.867 に答える