fail-fastポリシーとfail-safeは何ですか?

7889 ワード

fail-fastとは?簡単に言えば、異常が発生したシーンを優先し、異常が発生した場合、直接異常を投げ出し、プログラムを終了します.jclでのfail-fast?fail-fastは,我々が集合要素を遍歴する際に反復器を用いることが多いが,反復器が元素を遍歴する過程で集合の構造が変更されると,異常ConcurrentModificationExceptionが放出され,遍歴の継続を防止する.これがいわゆる急速な失敗メカニズムである.ここで注意すべきは,ここでいう構造が変更されることであり,例えば挿入と削除という操作であり,集合内の値を変更するだけでは異常は投げ出されない.
public static void main(String[] args) {
     
        List<String> list = new ArrayList<>();
        list.add("Java");
        list.add("C++");
        list.add("Python");
        list.add("PHP");
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
     
            String str = iterator.next();
            if (str.equals("PHP")) {
     
                list.remove(str);//           
            }
            System.out.println(str);
        }
    }

このメカニズムの最大の役割は、マルチスレッドの場合、マルチスレッドシーンで「汚れた読み取り」が発生しないことを保証することであり、スレッドが別のスレッドを読み込んで変更しようとすると、直接異常を投げ出すが、直接異常を投げ出すのは私たちが望んでいる結果ではなく、スレッドの安全な集合を採用すべきである.fail-safeとは?集合構造を変更するとfail‐fast機構は異常を放出する.しかし,fail−safeメカニズムを用いると異常は放出されない.これは、==集合の構造が変更されると、fail-safeメカニズムが元の集合のデータをコピーし、コピーしたデータを遍歴するためである.==たとえばCopyOnWriteArrayListというjucパッケージのスレッドセキュリティ集合クラスではfail-safeというポリシーが使用されている.
//CopyOnWriteArrayList   add  
 public boolean add(E e) {
     
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
     
            Object[] elements = getArray(); 
            int len = elements.length;
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            newElements[len] = e;
            setArray(newElements);
            return true;
        } finally {
     
            lock.unlock();
        }
    }

この集合のaddを例にとると,なぜCopyOnWriteArrayListがC o n c u r r e n tModificationException異常を投げ出さないのかは,copyの元のarrayにあり,copy配列上でadd操作を行うことで,CopyOnWriteArrayListにおけるarrayに全く影響を及ぼさない.もちろんremove、clearなどの他の方法でも同様のポリシーが使用されます.
fail-safeの欠点は上の2つのコア操作から分かるように、fail-safeには一定の欠陥がある.コピーには余分なスペースと時間のオーバーヘッドが必要です.2.すべて元の配列をコピーするため、マルチスレッドの場合、最新の内容が遍歴していることは保証されない可能性があります.