JDKでの同時バグ?

3173 ワード

最近Javaの同時研究をして、何気なくJDK 8のSystem.コンソール()メソッドのソースコードには、次のコードが表示されます.
    private static volatile Console cons = null;
    /**
     * Returns the unique {@link java.io.Console Console} object associated
     * with the current Java virtual machine, if any.
     *
     * @return  The system console, if any, otherwise <tt>null</tt>.
     *
     * @since   1.6
     */
     public static Console console() {
         if (cons == null) {
             synchronized (System.class) {
                 cons = sun.misc.SharedSecrets.getJavaIOAccess().console();
             }
         }
         return cons;
     }

第一に、これは有名な二重検査のロックに似ているのではないでしょうか.もっとよく見ると、バグがあるようで、こう書くべきだったようです.
     public static Console console() {
         if (cons == null) {
             synchronized (System.class) {
                  if (cons == null)
                        cons = sun.misc.SharedSecrets.getJavaIOAccess().console();
             }
         }
         return cons;
     }

これこそ正しい二重検査ロックの正しい書き方です.
ではJDKの書き方に問題があるようです.
a,bの2つのスレッドがif(cons==null){に実行された後、aスレッドがロックに入り、1つのconsオブジェクトが得られ、ロックが出て、bスレッドがロックに入り、また異なるconsオブジェクトが得られた場合、注釈の中の:Returns the unique{@link java.io.console Console}object associated*with the current Java virtual machine,if any.
矛盾した.
またsun.misc.SharedSecrets.getJavaIOAccess().console();戻るたびに同じオブジェクトであるため、synchronized(System.class)ロックを使用する必要はありません.
しかし、JDKでこのような低級なバグが発生した場合、また不可能だと感じているのではないでしょうか.しかし、自分がコードから見ても確かにバグがあるので、その経緯を知っておいてください.