当前位置: 首页>编程语言>正文

全面总结Android面试知识要点:Java核心基础相关(四)

馃敟甯稿湪娌宠竟璧帮紝鍝湁涓嶆箍闉嬨€傛垨璁搁潰璇曡繃绋嬩腑浣犻亣鍒扮殑闂灏卞湪杩欏憿锛?/strong>
馃敟鍏虫敞涓汉绠€浠嬶紝闈㈣瘯涓嶈糠璺?/strong>~

涓€銆丄QS鍘熺悊 锛堝皬绫?浜笢锛?/h2>

杩欓亾棰樻兂鑰冨療浠€涔堬紵

鏄惁浜嗚ВJava骞跺彂缂栫▼鐨勭浉鍏崇煡璇嗭紵

鑰冨療鐨勭煡璇嗙偣

AQS鐨勫師鐞?/p>

鑰冪敓搴旇濡備綍鍥炵瓟

浠€涔堟槸AQS

AQS鍗矨bstractQueuedSynchronizer锛屾槸涓€涓敤浜庢瀯寤洪攣鍜屽悓姝ュ櫒鐨勬鏋躲€傚畠鑳介檷浣庢瀯寤洪攣鍜屽悓姝ュ櫒鐨勫伐浣滈噺锛岃繕鍙互閬垮厤澶勭悊澶氫釜浣嶇疆涓婂彂鐢熺殑绔炰簤闂銆傚湪鍩轰簬AQS鏋勫缓鐨勫悓姝ュ櫒涓紝鍙彲鑳藉湪涓€涓椂鍒诲彂鐢熼樆濉烇紝浠庤€岄檷浣庝笂涓嬫枃鍒囨崲鐨勫紑閿€锛屽苟鎻愰珮鍚炲悙閲忋€?/p>

AQS鏍稿績鎬濇兂鏄紝濡傛灉琚姹傜殑鍏变韩璧勬簮绌洪棽锛岄偅涔堝氨灏嗗綋鍓嶈姹傝祫婧愮殑绾跨▼璁剧疆涓烘湁鏁堢殑宸ヤ綔绾跨▼锛屽皢鍏变韩璧勬簮璁剧疆涓洪攣瀹氱姸鎬侊紱濡傛灉鍏变韩璧勬簮琚崰鐢紝灏遍渶瑕佷竴瀹氱殑闃诲绛夊緟鍞ら啋鏈哄埗鏉ヤ繚璇侀攣鍒嗛厤銆傝繖涓満鍒朵富瑕佺敤鐨勬槸CLH闃熷垪鐨勫彉浣撳疄鐜扮殑锛屽皢鏆傛椂鑾峰彇涓嶅埌閿佺殑绾跨▼鍔犲叆鍒伴槦鍒椾腑銆?/p>

CLH

CLH鎸囩殑鏄細涓変綅鍒涗綔鑰呯殑鍚嶅瓧绠€绉?Craig銆丩andin and Hagersten (CLH)銆傛槸涓€绉嶅熀浜庨摼琛ㄧ殑鍙墿灞曘€侀珮鎬ц兘銆佸叕骞崇殑鑷棆閿侊紝鐢宠绾跨▼浠呬粎鍦ㄦ湰鍦板彉閲忎笂鑷棆锛屽畠涓嶆柇杞鍓嶉┍鐨勭姸鎬侊紝鍋囪鍙戠幇鍓嶉┍閲婃斁浜嗛攣灏辩粨鏉熻嚜鏃嬨€?/p>

AQS涓殑闃熷垪鏄疌LH鍙樹綋鐨勮櫄鎷熷弻鍚戦槦鍒楋紙FIFO锛夛紝AQS鏄€氳繃灏嗘瘡鏉¤姹傚叡浜祫婧愮殑绾跨▼灏佽鎴愪竴涓妭鐐规潵瀹炵幇閿佺殑鍒嗛厤銆?/p>

全面总结Android面试知识要点:Java核心基础相关(四),第1张

AQS鏀寔鐙崰閿侊紙exclusive锛夊拰鍏变韩閿?share)涓ょ妯″紡銆?/p>

  1. 鐙崰閿侊細鍙兘琚竴涓嚎绋嬭幏鍙栧埌(Reentrantlock)銆?/li>
  2. 鍏变韩閿侊細鍙互琚涓嚎绋嬪悓鏃惰幏鍙?CountDownLatch,ReadWriteLock)銆?/li>

鏃犺鏄嫭鍗犻攣杩樻槸鍏变韩閿侊紝鏈川涓婇兘鏄AQS鍐呴儴鐨勪竴涓彉閲弒tate鐨勮幏鍙栥€俿tate鏄竴涓師瀛愮殑int鍙橀噺锛岀敤鏉ヨ〃绀洪攣鐘舵€併€佽祫婧愭暟绛夈€?/p>

全面总结Android面试知识要点:Java核心基础相关(四),第2张

鍚屾闃熷垪鐨勪綔鐢ㄦ槸锛氬綋绾跨▼鑾峰彇璧勬簮澶辫触涔嬪悗锛屽氨杩涘叆鍚屾闃熷垪鐨勫熬閮ㄤ繚鎸佽嚜鏃嬬瓑寰咃紝涓嶆柇鍒ゆ柇鑷繁鏄惁鏄摼琛ㄧ殑澶磋妭鐐癸紝濡傛灉鏄ご鑺傜偣锛屽氨涓嶆柇鍙傝瘯鑾峰彇璧勬簮锛岃幏鍙栨垚鍔熷悗鍒欓€€鍑哄悓姝ラ槦鍒椼€?/p>

鏉′欢闃熷垪鏄负Lock瀹炵幇鐨勪竴涓熀纭€鍚屾鍣紝骞朵笖涓€涓嚎绋嬪彲鑳戒細鏈夊涓潯浠堕槦鍒楋紝鍙湁鍦ㄤ娇鐢ㄤ簡Condition鎵嶄細瀛樺湪鏉′欢闃熷垪銆?/p>

AQS涓寘鍚竴涓唴閮ㄧ被:Node銆傝鍐呴儴绫绘槸涓€涓弻鍚戦摼琛紝淇濆瓨鍓嶅悗鑺傜偣锛岀劧鍚庢瘡涓妭鐐瑰瓨鍌ㄤ簡褰撳墠鐨勭姸鎬亀aitStatus銆佸綋鍓嶇嚎绋媡hread銆傚悓姝ラ槦鍒楀拰鏉′欢闃熷垪閮芥槸鐢变竴涓釜Node缁勬垚鐨勩€?/p>

 static final class Node {
        static final Node EXCLUSIVE = null;

        //褰撳墠鑺傜偣鐢变簬瓒呮椂鎴栦腑鏂鍙栨秷
        static final int CANCELLED =  1;
     
        //琛ㄧず褰撳墠鑺傜偣鐨勫墠鑺傜偣琚樆濉?
        static final int SIGNAL    = -1;
        
        //褰撳墠鑺傜偣鍦ㄧ瓑寰卌ondition
        static final int CONDITION = -2;
      
        //鐘舵€侀渶瑕佸悜鍚庝紶鎾?
        static final int PROPAGATE = -3;
        
        volatile int waitStatus;
        
        volatile Node prev;
        volatile Node next;
        volatile Thread thread;

        Node nextWaiter;

        final boolean isShared() {
            return nextWaiter == SHARED;
        }

        final Node predecessor() throws NullPointerException {
            Node p = prev;
            if (p == null)
                throw new NullPointerException();
            else
                return p;
        }

        Node() {    // Used to establish initial head or SHARED marker
        }

        Node(Thread thread, Node mode) {     // Used by addWaiter
            this.nextWaiter = mode;
            this.thread = thread;
        }

        Node(Thread thread, int waitStatus) { // Used by Condition
            this.waitStatus = waitStatus;
            this.thread = thread;
        }
    }

鐙崰妯″紡涓嬭幏鍙栬祫婧?

    public final void acquire(int arg) {
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

acquire(int arg)棣栧厛璋冪敤tryAcquire(arg)灏濊瘯鐩存帴鑾峰彇璧勬簮锛屽鏋滆幏鍙栨垚鍔燂紝鍥犱负涓庤繍绠楃殑鐭矾鎬ц川锛屽氨涓嶅啀鎵ц鍚庨潰鐨勫垽鏂紝鐩存帴杩斿洖銆倀ryAcquire(int arg)鐨勫叿浣撳疄鐜扮敱瀛愮被璐熻矗銆傚鏋滄病鏈夌洿鎺ヨ幏鍙栧埌璧勬簮锛屽氨灏嗗綋鍓嶇嚎绋嬪姞鍏ョ瓑寰呴槦鍒楃殑灏鹃儴锛屽苟鏍囪涓虹嫭鍗犳ā寮忥紝浣跨嚎绋嬪湪绛夊緟闃熷垪涓嚜鏃嬬瓑寰呰幏鍙栬祫婧愶紝鐩村埌鑾峰彇璧勬簮鎴愬姛鎵嶈繑鍥炪€傚鏋滅嚎绋嬪湪绛夊緟鐨勮繃绋嬩腑琚腑鏂繃锛屽氨杩斿洖true锛屽惁鍒欒繑鍥瀎alse銆?/p>

濡傛灉acquireQueued(addWaiter(Node.EXCLUSIVE), arg)鎵ц杩囩▼涓涓柇杩囷紝閭d箞if璇彞鐨勬潯浠跺氨鍏ㄩ儴鎴愮珛锛屽氨浼氭墽琛宻elfInterrupt();鏂规硶銆傚洜涓哄湪绛夊緟闃熷垪涓嚜鏃嬬姸鎬佺殑绾跨▼鏄笉浼氬搷搴斾腑鏂殑锛屽畠浼氭妸涓柇璁板綍涓嬫潵锛屽鏋滃湪鑷棆鏃跺彂鐢熻繃涓柇锛屽氨杩斿洖true銆傜劧鍚庡氨浼氭墽琛宻elfInterrupt()鏂规硶锛岃€岃繖涓柟娉曞氨鏄畝鍗曠殑涓柇褰撳墠绾跨▼Thread.currentThread().interrupt();鍏朵綔鐢ㄥ氨鏄ˉ涓婂湪鑷棆鏃舵病鏈夊搷搴旂殑涓柇銆?/p>

鍙互鐪嬪嚭鍦ㄦ暣涓柟娉曚腑锛屾渶閲嶈鐨勫氨鏄痑cquireQueued(addWaiter(Node.EXCLUSIVE), arg)銆傛垜浠鍏堢湅Node addWaiter(Node mode)鏂规硶锛岄【鍚嶆€濅箟锛岃繖涓柟娉曠殑浣滅敤灏辨槸娣诲姞涓€涓瓑寰呰€咃紝鏍规嵁涔嬪墠瀵笰QS涓暟鎹粨鏋勭殑鍒嗘瀽锛屽彲浠ョ煡閬擄紝娣诲姞绛夊緟鑰呭氨鏄皢璇ヨ妭鐐瑰姞鍏ョ瓑寰呴槦鍒椼€?/p>

private Node addWaiter(Node mode) {
        Node node = new Node(Thread.currentThread(), mode);
        // Try the fast path of enq; backup to full enq on failure
        Node pred = tail;
        //灏濊瘯蹇€熷叆闃?
        if (pred != null) { //闃熷垪宸茬粡鍒濆鍖?
            node.prev = pred;
            if (compareAndSetTail(pred, node)) {
                pred.next = node;
                return node; //蹇€熷叆闃熸垚鍔熷悗锛屽氨鐩存帴杩斿洖浜?
            }
        }
        //蹇€熷叆闃熷け璐ワ紝涔熷氨鏄闃熷垪閮借繕娌″垵濮嬪寲锛屽氨浣跨敤enq
        enq(node);
        return node;
    }
    
    //鎵ц鍏ラ槦
     private Node enq(final Node node) {
        for (;;) {
            Node t = tail;
            if (t == null) { // Must initialize
            //濡傛灉闃熷垪涓虹┖锛岀敤涓€涓┖鑺傜偣鍏呭綋闃熷垪澶?
                if (compareAndSetHead(new Node()))
                    tail = head;//灏鹃儴鎸囬拡涔熸寚鍚戦槦鍒楀ご
            } else {
                //闃熷垪宸茬粡鍒濆鍖栵紝鍏ラ槦
                node.prev = t;
                if (compareAndSetTail(t, node)) {
                    t.next = node;
                    return t;//鎵撴柇寰幆
                }
            }
        }
    }
final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
                final Node p = node.predecessor();//鎷垮埌node鐨勪笂涓€涓妭鐐?
                //鍓嶇疆鑺傜偣涓篽ead锛岃鏄庡彲浠ュ皾璇曡幏鍙栬祫婧愩€傛帓闃熸垚鍔熷悗锛屽皾璇曟嬁閿?
                if (p == head && tryAcquire(arg)) {
                    setHead(node);//鑾峰彇鎴愬姛锛屾洿鏂癶ead鑺傜偣
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                }
                //灏濊瘯鎷块攣澶辫触鍚庯紝鏍规嵁鏉′欢杩涜park
                if (shouldParkAfterFailedAcquire(p, node) &&
                    parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }
    //鑾峰彇璧勬簮澶辫触鍚庯紝妫€娴嬪苟鏇存柊绛夊緟鐘舵€?
    private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
        int ws = pred.waitStatus;
        if (ws == Node.SIGNAL)
            /*
             * This node has already set status asking a release
             * to signal it, so it can safely park.
             */
            return true;
        if (ws > 0) {
            /*
             * Predecessor was cancelled. Skip over predecessors and
             * indicate retry.
             */
            do {
            //濡傛灉鍓嶈妭鐐瑰彇娑堜簡锛岄偅灏卞線鍓嶆壘鍒颁竴涓瓑寰呯姸鎬佺殑鎺ュ緟浣狅紝骞舵帓鍦ㄥ畠鐨勫悗闈?
                node.prev = pred = pred.prev;
            } while (pred.waitStatus > 0);
            pred.next = node;
        } else {
            /*
             * waitStatus must be 0 or PROPAGATE.  Indicate that we
             * need a signal, but don't park yet.  Caller will need to
             * retry to make sure it cannot acquire before parking.
             */
            compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
        }
        return false;
    }
    //闃诲褰撳墠绾跨▼锛岃繑鍥炰腑鏂姸鎬?
    private final boolean parkAndCheckInterrupt() {
        LockSupport.park(this);
        return Thread.interrupted();
    }

鍏钩閿佺殑瀹炵幇

鍦ㄥ苟鍙戠幆澧冧腑锛屾瘡涓嚎绋嬪湪鑾峰彇閿佹椂浼氬厛鏌ョ湅姝ら攣缁存姢鐨勭瓑寰呴槦鍒楋紝濡傛灉涓虹┖锛屾垨鑰呭綋鍓嶇嚎绋嬫槸绛夊緟闃熷垪鐨勭涓€涓紝灏卞崰鏈夐攣锛屽惁鍒欏氨浼氬姞鍏ュ埌绛夊緟闃熷垪涓紝浠ュ悗浼氭寜鐓IFO鐨勮鍒欎粠闃熷垪涓彇鍒拌嚜宸便€傚叕骞抽攣鐨勪紭鐐规槸绛夊緟閿佺殑绾跨▼涓嶄細楗挎銆傜己鐐规槸鏁翠綋鍚炲悙鏁堢巼鐩稿闈炲叕骞抽攣瑕佷綆锛岀瓑寰呴槦鍒椾腑闄ょ涓€涓嚎绋嬩互澶栫殑鎵€鏈夌嚎绋嬮兘浼氶樆濉烇紝CPU鍞ら啋闃诲绾跨▼鐨勫紑閿€姣旈潪鍏钩閿佸ぇ銆?/p>

protected final boolean tryAcquire(int acquires) {
     final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {//鐘舵€佷负0琛ㄧず鍙互鍔犻攣
                if (!hasQueuedPredecessors() && //hasQueuedPredecessors琛ㄧず涔嬪墠鐨勭嚎绋嬫槸鍚︽湁鍦ㄦ帓闃熺殑锛岃繖閲屽姞浜嗭紒琛ㄧず娌℃湁鎺掗槦
                    compareAndSetState(0, acquires)) { //閭d箞灏卞幓灏濊瘯cas state
                    setExclusiveOwnerThread(current); //濡傛灉cas鎴愬姛璁剧疆鎺掍粬绾跨▼涓哄綋鍓嶇嚎绋嬶紝琛ㄧず鎴愬姛寰楀埌閿?
                    return true;
                }
            }
            else if (current == getExclusiveOwnerThread()) {//濡傛灉褰撳墠鐨勬帓浠栫嚎绋嬫槸褰撳墠绾跨▼锛岃〃绀烘槸閲嶅叆
                int nextc = c + acquires; //閲嶅叆璁℃暟鍣ㄥ鍔?
                if (nextc < 0)
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);//鍥犱负宸茬粡鑾峰緱閿佷簡锛屾墍浠ヤ笉鐢╟as鍘昏锛岀洿鎺ヨ鍊煎氨琛?
                return true;
            }
            return false;
}

闈炲叕骞抽攣鐨勫疄鐜?/h4>

鐩存帴灏濊瘯鍗犳湁閿侊紝濡傛灉灏濊瘯澶辫触锛屽氨鍐嶉噰鐢ㄧ被浼煎叕骞抽攣閭g鏂瑰紡銆傞潪鍏钩閿佺殑浼樼偣鏄彲浠ュ噺灏戝敜璧风嚎绋嬬殑寮€閿€锛屾暣浣撶殑鍚炲悙鏁堢巼楂橈紝鍥犱负绾跨▼鏈夊嚑鐜囦笉闃诲鐩存帴鑾峰緱閿侊紝CPU涓嶅繀鍞ら啋鎵€鏈夌嚎绋嬨€傜己鐐规槸澶勪簬绛夊緟闃熷垪涓殑绾跨▼鍙兘浼氶タ姝伙紝鎴栬€呯瓑寰堜箙鎵嶄細鑾峰緱閿併€?/p>

final boolean nonfairTryAcquire(int acquires) {
    // 鑾峰彇褰撳墠绾跨▼
    final Thread current = Thread.currentThread();
    // 鑾峰彇褰撳墠state鐨勫€?
    int c = getState(); 
    if (c == 0) {
      // 鐪嬬湅璁剧疆鍊兼槸鍚﹁兘鎴愬姛
            if (compareAndSetState(0, acquires)) {
           // 鍒欏皢褰撳墠绾跨▼璁剧疆涓虹嫭鍗犵嚎绋?
            setExclusiveOwnerThread(current);
            return true;
        }
    }
 // 杩斿洖鐢眘etExclusiveOwnerThread璁剧疆鐨勬渶鍚庝竴涓嚎绋嬶紱濡傛灉浠庝笉璁剧疆锛屽垯杩斿洖null 
    else if (current == getExclusiveOwnerThread()) {
        int nextc = c + acquires;
        if (nextc < 0) // overflow
            throw new Error("Maximum lock count exceeded");
        // 璁剧疆state鐨勫€?
        setState(nextc);
        return true;
    }
    return false;
}

閲婃斁閿佸疄鐜?/h4>

閲婃斁閿佷唬鐮佸垎鏋愶細灏濊瘯閲婃斁姝ら攣銆傚鏋滃綋鍓嶇嚎绋嬫槸姝ら攣鐨勬寔鏈夎€咃紝鍒欎繚鐣欒鏁板皢鍑忓皯銆?濡傛灉淇濇寔璁℃暟鐜板湪涓洪浂锛屽垯閲婃斁閿佸畾銆?濡傛灉褰撳墠绾跨▼涓嶆槸姝ら攣鐨勬寔鏈夎€咃紝鍒欐姏鍑篒llegalMonitorStateException銆?/p>

public void unlock() {
    sync.release(1);
}

sync.release(1) 璋冪敤鐨勬槸AbstractQueuedSynchronizer涓殑release鏂规硶

## AbstractQueuedSynchronizer
public final boolean release(int arg) {
    if (tryRelease(arg)) {
        Node h = head;
        if (h != null && h.waitStatus != 0)
            unparkSuccessor(h);
        return true;
    }
    return false;
}

鍒嗘瀽tryRelease(arg)鏂规硶锛宼ryRelease(arg)璇ユ柟娉曡皟鐢ㄧ殑鏄疪eentrantLock涓?/p>

protected final boolean tryRelease(int releases) {
// 鑾峰彇褰撳墠閿佹寔鏈夌殑绾跨▼鏁伴噺鍜岄渶瑕侀噴鏀剧殑鍊艰繘琛岀浉鍑?
    int c = getState() - releases; 
    // 濡傛灉褰撳墠绾跨▼涓嶆槸閿佸崰鏈夌殑绾跨▼鎶涘嚭寮傚父
    if (Thread.currentThread() != getExclusiveOwnerThread())
        throw new IllegalMonitorStateException();
    boolean free = false;
    // 濡傛灉姝ゆ椂c = 0灏辨剰鍛崇潃state = 0锛屽綋鍓嶉攣娌℃湁琚换鎰忕嚎绋嬪崰鏈?
    // 灏嗗綋鍓嶆墍鐨勫崰鏈夌嚎绋嬭缃负绌?
    if (c == 0) {
        free = true;
        setExclusiveOwnerThread(null);
    }
    // 璁剧疆state鐨勫€间负 0
    setState(c);
    return free;
}

濡傛灉澶磋妭鐐逛笉涓虹┖锛屽苟涓攚aitStatus != 0锛屽敜閱掑悗缁妭鐐瑰鏋滃瓨鍦ㄧ殑璇濄€傝繖閲岀殑鍒ゆ柇鏉′欢涓轰粈涔堟槸h != null && h.waitStatus != 0锛熷洜涓篽 == null鐨勮瘽锛孒ead杩樻病鍒濆鍖栥€傚垵濮嬫儏鍐典笅锛宧ead == null锛岀涓€涓妭鐐瑰叆闃燂紝Head浼氳鍒濆鍖栦竴涓櫄鎷熻妭鐐广€傛墍浠ヨ锛岃繖閲屽鏋滆繕娌℃潵寰楀強鍏ラ槦锛屽氨浼氬嚭鐜癶ead == null 鐨勬儏鍐点€?/p>

  1. h != null && waitStatus == 0 琛ㄦ槑鍚庣户鑺傜偣瀵瑰簲鐨勭嚎绋嬩粛鍦ㄨ繍琛屼腑锛屼笉闇€瑕佸敜閱?/li>
  2. h != null && waitStatus < 0 琛ㄦ槑鍚庣户鑺傜偣鍙兘琚樆濉炰簡锛岄渶瑕佸敜閱?/li>
private void unparkSuccessor(Node node) {
// 鑾峰彇澶寸粨鐐箇aitStatus
    int ws = node.waitStatus;
    if (ws < 0)
        compareAndSetWaitStatus(node, ws, 0);
// 鑾峰彇褰撳墠鑺傜偣鐨勪笅涓€涓妭鐐?
    Node s = node.next;
//濡傛灉涓嬩釜鑺傜偣鏄痭ull鎴栬€呬笅涓妭鐐硅cancelled锛屽氨鎵惧埌闃熷垪鏈€寮€濮嬬殑闈瀋ancelled鐨勮妭鐐?
    if (s == null || s.waitStatus > 0) {
        s = null;
        // 灏变粠灏鹃儴鑺傜偣寮€濮嬫壘寰€鍓嶉亶鍘嗭紝鎵惧埌闃熷垪涓涓€涓獁aitStatus<0鐨勮妭鐐广€?
        for (Node t = tail; t != null && t != node; t = t.prev)
            if (t.waitStatus <= 0)
                s = t;
    }
  // 濡傛灉褰撳墠鑺傜偣鐨勪笅涓妭鐐逛笉涓虹┖锛岃€屼笖鐘舵€?lt;=0锛屽氨鎶婂綋鍓嶈妭鐐瑰敜閱?
    if (s != null)
        LockSupport.unpark(s.thread);
}

涓轰粈涔堣浠庡悗寰€鍓嶆壘绗竴涓潪Cancelled鐨勮妭鐐癸紵

private Node addWaiter(Node mode) {
    Node node = new Node(Thread.currentThread(), mode);
    Node pred = tail;
    if (pred != null) {
        node.prev = pred;
        if (compareAndSetTail(pred, node)) {
            pred.next = node;
            return node;
        }
    }
    enq(node);
    return node;
}

浠庢澶勫彲浠ョ湅鍒帮紝鑺傜偣鍏ラ槦骞朵笉鏄師瀛愭搷浣滐紝涔熷氨鏄锛宯ode.prev = pred, compareAndSetTail(pred, node) 杩欎袱涓湴鏂瑰彲浠ョ湅浣淭ail鍏ラ槦鐨勫師瀛愭搷浣滐紝浣嗘槸姝ゆ椂pred.next = node;杩樻病鎵ц锛屽鏋滆繖涓椂鍊欐墽琛屼簡unparkSuccessor鏂规硶锛屽氨娌″姙娉曚粠鍓嶅線鍚庢壘浜嗭紝鎵€浠ラ渶瑕佷粠鍚庡線鍓嶆壘銆傝繕鏈変竴鐐瑰師鍥狅紝鍦ㄤ骇鐢烠ANCELLED鐘舵€佽妭鐐圭殑鏃跺€欙紝鍏堟柇寮€鐨勬槸Next鎸囬拡锛孭rev鎸囬拡骞舵湭鏂紑锛屽洜姝や篃鏄繀椤昏浠庡悗寰€鍓嶉亶鍘嗘墠鑳藉閬嶅巻瀹屽叏閮ㄧ殑Node銆?鎵€浠ワ紝濡傛灉鏄粠鍓嶅線鍚庢壘锛岀敱浜庢瀬绔儏鍐典笅鍏ラ槦鐨勯潪鍘熷瓙鎿嶄綔鍜孋ANCELLED鑺傜偣浜х敓杩囩▼涓柇寮€Next鎸囬拡鐨勬搷浣滐紝鍙兘浼氬鑷存棤娉曢亶鍘嗘墍鏈夌殑鑺傜偣銆傛墍浠ワ紝鍞ら啋瀵瑰簲鐨勭嚎绋嬪悗锛屽搴旂殑绾跨▼灏变細缁х画寰€涓嬫墽琛屻€?/p>

全面总结Android面试知识要点:Java核心基础相关(四),第3张

浜屻€丷eentrantLock鐨勫疄鐜板師鐞?/h2>

杩欓亾棰樻兂鑰冨療浠€涔堬紵

  1. 鏄惁浜嗚В骞跺彂鐩稿叧鐨勭悊璁虹煡璇?/li>
  2. 鏄惁瀵逛簬閿佹満鍒舵湁涓叏闈㈢殑鐞嗚璁ょ煡
  3. 鏄惁瀵逛簬AQS鍘熺悊鏈夎嚜宸辩殑鐞嗚В

鑰冨療鐨勭煡璇嗙偣

  1. 閿佺殑鍒嗙被锛堝叕骞抽攣銆侀噸鍏ラ攣銆侀噸鍔涘害閿佺瓑绛夛級
  2. ReentrantLock瀹炵幇鏂瑰紡涓嶴ynchronized瀹炵幇鏂瑰紡鐨勫紓鍚岀偣

鑰冪敓搴旇濡備綍鍥炵瓟

Java涓殑澶ч儴鍒嗗悓姝ョ被锛圠ock銆丼emaphore銆丷eentrantLock绛夛級閮芥槸鍩轰簬闃熷垪鍚屾鍣ㄢ€擜QS瀹炵幇鐨勩€侫QS鍘熺悊瑙?銆?.5 AQS鍘熺悊銆?/strong> 銆?/p>

鍦≧eentrantLock涓湁涓€涓娊璞$被Sync锛?/p>

private final Sync sync;
abstract static class Sync extends AbstractQueuedSynchronizer {
    ...    
}

鍙互鐪嬪埌Sync灏辩户鎵胯嚜AQS锛岃€孯eentrantLock鐨刲ock瑙i攣銆乽nlock閲婃斁閿佺瓑鎿嶄綔鍏跺疄閮芥槸鍊熷姪鐨剆ync鏉ュ畬鎴愩€?/p>

public void lock() {
    sync.lock();
}
public void unlock() {
    sync.release(1);
}

Sync鏄釜鎶借薄绫伙紝ReentrantLock鏍规嵁浼犲叆鏋勯€犳柟娉曠殑甯冨皵鍨嬪弬鏁板疄渚嬪寲鍑篠ync鐨勫疄鐜扮被FairSync鍜孨onfairSync锛屽垎鍒〃绀哄叕骞抽攣鍜岄潪鍏钩閿併€?/p>

public ReentrantLock() {
    sync = new NonfairSync();
}

public ReentrantLock(boolean fair) {
    sync = fair new FairSync() : new NonfairSync();
}

ReentrantLock涓嶢QS鐨勫叧绯诲涓嬶細

全面总结Android面试知识要点:Java核心基础相关(四),第4张

NonfairSync

鍦≧eentrantLock鐨勯粯璁ゆ棤鍙傛瀯閫犳柟娉曚腑锛宻ync浼氳鏄疄渚嬪寲涓猴細NonfairSync 琛ㄧず闈炲叕骞抽攣銆?/p>

lock
static final class NonfairSync extends Sync {
    final void lock() {
        if (compareAndSetState(0, 1))
            setExclusiveOwnerThread(Thread.currentThread());
        else
            acquire(1);
    }
}

NonfairSync灏辨槸涓€涓狝QS銆傚洜姝ゅ湪鎵цlock鏃讹紝浼氶鍏堝埄鐢–AS锛?銆?.4 CAS鏃犻攣缂栫▼鍘熺悊銆?/strong> 锛夊皾璇曡缃瓵QS鐨剆tate涓?銆傚鏋滆缃垚鍔熻〃绀烘垚鍔熻幏鍙栭攣锛涘惁鍒欒〃绀哄叾浠栫嚎绋嬪凡缁忓崰鐢紝姝ゆ椂浼氫娇鐢?code>AQS#acquire灏嗗皾璇曡幏鍙栭攣澶辫触鐨勭嚎绋嬫斁鍏QS鐨勭瓑寰呴槦鍒楄繘琛岀瓑寰呭苟涓斿皢绾跨▼鎸傝捣銆?/p>

unlock

lock鑾峰彇閿侀渶瑕佸state杩涜鍔?锛岄偅涔堝浜庨噸鍏ラ攣鑰岃█锛岄噸鍏ヤ竴娆″氨闇€瑕佸state鎵ц涓€娆″姞1銆傝繖鏍峰瓙锛屽湪瑙i攣鐨勬椂鍊欙紝姣忔unlock灏卞state鍑忎竴锛岀瓑鍒皊tate鐨勫€间负0鐨勬椂鍊欙紝鎵嶈兘鍞ら啋涓嬩竴涓瓑寰呯嚎绋嬨€?/p>

鍥犳ReentrantLock#unlock锛屽疄闄呬笂灏辨槸鎵ц浜咥QS鐨剅elease(1)锛?/p>

public void unlock() {
    sync.release(1);
}

FairSync

瀵逛簬NonfairSync 鑰岃█锛岀嚎绋嬪彧瑕佹墽琛宭ock璇锋眰锛屽氨浼氶┈涓婂皾璇曡幏鍙栭攣锛屼笉浼氱AQS褰撳墠绠$悊鐨勭瓑寰呴槦鍒椾腑鏄惁瀛樺湪姝e湪绛夊緟鐨勭嚎绋嬶紝杩欏浜庣瓑寰呯殑绾跨▼涓嶅叕骞筹紝鍥犳NonfairSync琛ㄧず闈炲叕骞抽攣銆?/p>

鑰?strong>FairSync琛ㄧず鍏钩閿侊紝浼氬湪lock璇锋眰杩涜鏃讹紝鍏堝垽鏂瑼QS绠$悊鐨勭瓑寰呴槦鍒椾腑鏄惁宸茬粡鏈夋鍦ㄧ瓑寰呯殑绾跨▼锛屾湁鐨勮瘽灏变笉浼氬皾璇曡幏鍙栭攣锛岀洿鎺ヨ繘鍏ョ瓑寰呴槦鍒楋紝淇濊瘉浜嗗叕骞虫€с€傛鏃?code>FairSync#lock瀹為檯涓婃墽琛岀殑灏辨槸AQS鐨刟cquire

static final class FairSync extends Sync {
    final void lock() {
        acquire(1);
    }
}

涓夈€丼ynchronized鐨勫師鐞嗕互鍙婁笌ReentrantLock鐨勫尯鍒€傦紙360锛?/h2>

杩欓亾棰樻兂鑰冨療浠€涔堬紵

  1. 鏄惁浜嗚В骞跺彂鐩稿叧鐨勭悊璁虹煡璇?/li>
  2. 鏄惁瀵逛簬閿佹満鍒舵湁涓叏闈㈢殑鐞嗚璁ょ煡
  3. 鏄惁瀵逛簬AQS鍘熺悊鏈夎嚜宸辩殑鐞嗚В

鑰冨療鐨勭煡璇嗙偣

  1. 閿佺殑鍒嗙被锛堝叕骞抽攣銆侀噸鍏ラ攣銆侀噸鍔涘害閿佺瓑绛夛級
  2. ReentrantLock瀹炵幇鏂瑰紡涓嶴ynchronized瀹炵幇鏂瑰紡鐨勫紓鍚岀偣

鑰冪敓搴旇濡備綍鍥炵瓟

Synchronized鐨勫師鐞嗚 銆?.8 Synchronized鍦↗DK1.6涔嬪悗鍋氫簡鍝簺浼樺寲銆?/strong> 銆?/p>

ReentrantLock涓嶴ynchronized鐨勫尯鍒紝闄や簡涓€涓槸Java绫诲疄鐜帮紝涓€涓槸鍏抽敭瀛椾箣澶栵紝杩樺寘鎷細

全面总结Android面试知识要点:Java核心基础相关(四),第5张

闄ゆ涔嬪锛孯eenTrantLock鐩稿浜嶴ynchronized杩樻嫢鏈夎嚜宸辩殑鐙湁鐗规€э細

  • ReenTrantLock鍙互鎸囧畾鏄叕骞抽攣杩樻槸闈炲叕骞抽攣銆傝€宻ynchronized鍙兘鏄潪鍏钩閿併€傛墍璋撶殑鍏钩閿佸氨鏄厛绛夊緟鐨勭嚎绋嬪厛鑾峰緱閿併€?/li>
  • ReenTrantLock鎻愪緵浜嗕竴涓狢ondition锛堟潯浠讹級绫伙紝鐢ㄦ潵瀹炵幇鍒嗙粍鍞ら啋闇€瑕佸敜閱掔殑绾跨▼浠紝鑰屼笉鏄儚synchronized瑕佷箞闅忔満鍞ら啋涓€涓嚎绋嬭涔堝敜閱掑叏閮ㄧ嚎绋嬨€?/li>
  • ReenTrantLock鎻愪緵浜嗕竴绉嶈兘澶熶腑鏂瓑寰呴攣鐨勭嚎绋嬬殑鏈哄埗锛岄€氳繃lock.lockInterruptibly()鏉ュ疄鐜拌繖涓満鍒躲€?/li>

4.8 volatile鍏抽敭瀛楀共浜嗕粈涔堬紵锛堜粈涔堝彨鎸囦护閲嶆帓锛?锛堝瓧鑺傝烦鍔級

杩欓亾棰樻兂鑰冨療浠€涔堬紵

鏄惁浜嗚Вvolatile鍏抽敭瀛椾笌鐪熷疄鍦烘櫙浣跨敤

鑰冨療鐨勭煡璇嗙偣

volatile鍏抽敭瀛楃殑姒傚康鍦ㄩ」鐩腑浣跨敤涓庡熀鏈煡璇?/p>

鑰冪敓搴旇濡備綍鍥炵瓟

volatile鏄痡ava鎻愪緵鐨勫彲浠ュ0鏄庡湪鎴愬憳灞炴€у墠鐨勪竴涓叧閿瓧銆傚湪澹版槑涓寘鍚鍏抽敭瀛楃殑浣滅敤鏈夛細

淇濊瘉鍐呭瓨鍙鎬?/h4>

鍙鎬ф槸鎸囩嚎绋嬩箣闂寸殑鍙鎬э紝涓€涓嚎绋嬩慨鏀圭殑鐘舵€佸鍙︿竴涓嚎绋嬫槸鍙鐨勩€備篃灏辨槸涓€涓嚎绋嬩慨鏀圭殑缁撴灉锛屽彟涓€涓嚎绋嬮┈涓婂氨鑳界湅鍒般€?/p>

褰撳闈瀡olatile鍙橀噺杩涜璇诲啓鐨勬椂鍊欙紝姣忎釜绾跨▼鍏堜粠涓诲唴瀛樻嫹璐濆彉閲忓埌CPU缂撳瓨涓紝濡傛灉璁$畻鏈烘湁澶氫釜CPU锛屾瘡涓嚎绋嬪彲鑳藉湪涓嶅悓鐨凜PU涓婅澶勭悊锛岃繖鎰忓懗鐫€姣忎釜绾跨▼鍙互鎷疯礉鍒颁笉鍚岀殑CPU cache涓€?/p>

volatile鍙橀噺涓嶄細琚紦瀛樺湪瀵勫瓨鍣ㄦ垨鑰呭鍏朵粬澶勭悊鍣ㄤ笉鍙鐨勫湴鏂癸紝淇濊瘉浜嗘瘡娆¤鍐欏彉閲忛兘浠庝富鍐呭瓨涓锛岃烦杩嘋PU cache杩欎竴姝ャ€傚綋涓€涓嚎绋嬩慨鏀逛簡杩欎釜鍙橀噺鐨勫€硷紝鏂板€煎浜庡叾浠栫嚎绋嬫槸绔嬪嵆寰楃煡鐨勩€?/p>

绂佹鎸囦护閲嶆帓

鎸囦护閲嶆帓搴忔槸JVM涓轰簡浼樺寲鎸囦护銆佹彁楂樼▼搴忚繍琛屾晥鐜囷紝鍦ㄤ笉褰卞搷鍗曠嚎绋嬬▼搴忔墽琛岀粨鏋滅殑鍓嶆彁涓嬶紝灏藉彲鑳藉湴鎻愰珮骞惰搴︺€傛寚浠ら噸鎺掑簭鍖呮嫭缂栬瘧鍣ㄩ噸鎺掑簭鍜岃繍琛屾椂閲嶆帓搴忋€?/p>

latile鍙橀噺绂佹鎸囦护閲嶆帓搴忋€傞拡瀵箆olatile淇グ鐨勫彉閲忥紝鍦ㄨ鍐欐搷浣滄寚浠ゅ墠鍚庝細鎻掑叆鍐呭瓨灞忛殰锛屾寚浠ら噸鎺掑簭鏃朵笉鑳芥妸鍚庨潰鐨勬寚浠ら噸鎺掑簭鍒板唴瀛樺睆

绀轰緥璇存槑锛?/p>

绀轰緥璇存槑锛?
double r = 2.1; //(1) 
double pi = 3.14;//(2) 
double area = pi*r*r;//(3)

铏界劧浠g爜璇彞鐨勫畾涔夐『搴忎负1->2->3锛屼絾鏄绠楅『搴?->2->3涓?->1->3瀵圭粨鏋滃苟鏃犲奖鍝嶏紝鎵€浠ョ紪璇戞椂鍜岃繍琛屾椂鍙互鏍规嵁闇€瑕佸1銆?璇彞杩涜閲嶆帓搴忋€?/p>

鎸囦护閲嶆帓甯︽潵鐨勯棶棰?/h5>

濡傛灉涓€涓搷浣滀笉鏄師瀛愮殑锛屽氨浼氱粰JVM鐣欎笅閲嶆帓鐨勬満浼氥€?/p>

绾跨▼A涓?
{
    context = loadContext();
    inited = true;
}
 
绾跨▼B涓?
{
    if (inited) 
        fun(context);
}

濡傛灉绾跨▼A涓殑鎸囦护鍙戠敓浜嗛噸鎺掑簭锛岄偅涔圔涓緢鍙兘灏变細鎷垮埌涓€涓皻鏈垵濮嬪寲鎴栧皻鏈垵濮嬪寲瀹屾垚鐨刢ontext,浠庤€屽紩鍙戠▼搴忛敊璇€?/p>

绂佹鎸囦护閲嶆帓鐨勫師鐞?/h5>

volatile鍏抽敭瀛楁彁渚涘唴瀛樺睆闅滅殑鏂瑰紡鏉ラ槻姝㈡寚浠よ閲嶆帓锛岀紪璇戝櫒鍦ㄧ敓鎴愬瓧鑺傜爜鏂囦欢鏃讹紝浼氬湪鎸囦护搴忓垪涓彃鍏ュ唴瀛樺睆闅滄潵绂佹鐗瑰畾绫诲瀷鐨勫鐞嗗櫒閲嶆帓搴忋€?/p>

JVM鍐呭瓨灞忛殰鎻掑叆绛栫暐锛?/p>

鍦ㄦ瘡涓獀olatile鍐欐搷浣滅殑鍓嶉潰鎻掑叆涓€涓猄toreStore灞忛殰锛?/p>

鍦ㄦ瘡涓獀olatile鍐欐搷浣滅殑鍚庨潰鎻掑叆涓€涓猄toreLoad灞忛殰锛?/p>

鍦ㄦ瘡涓獀olatile璇绘搷浣滅殑鍚庨潰鎻掑叆涓€涓狶oadLoad灞忛殰锛?/p>

鍦ㄦ瘡涓獀olatile璇绘搷浣滅殑鍚庨潰鎻掑叆涓€涓狶oadStore灞忛殰銆?/p>

鎸囦护閲嶆帓鍦ㄥ弻閲嶉攣瀹氬崟渚嬫ā寮忎腑鐨勫奖鍝?/strong> 鍩轰簬鍙岄噸妫€楠岀殑鍗曚緥妯″紡(鎳掓眽鍨?

public class Singleton3 {
    private static Singleton3 instance = null;
 
    private Singleton3() {}
 
    public static Singleton3 getInstance() {
        if (instance == null) {
            synchronized(Singleton3.class) {
                if (instance == null)
                    instance = new Singleton3();// 闈炲師瀛愭搷浣?
            }
        }
 
        return instance;
    }
}

instance= new Singleton()骞朵笉鏄竴涓師瀛愭搷浣滐紝鍏跺疄闄呬笂鍙互鎶借薄涓轰笅闈㈠嚑鏉VM鎸囦护锛?/p>

memory =allocate();    //1锛氬垎閰嶅璞$殑鍐呭瓨绌洪棿 
ctorInstance(memory);  //2锛氬垵濮嬪寲瀵硅薄 
instance =memory;     //3锛氳缃甶nstance鎸囧悜鍒氬垎閰嶇殑鍐呭瓨鍦板潃

涓婇潰鎿嶄綔2渚濊禆浜庢搷浣?锛屼絾鏄搷浣?骞朵笉渚濊禆浜庢搷浣?銆傛墍浠VM鏄彲浠ラ拡瀵瑰畠浠繘琛屾寚浠ょ殑浼樺寲閲嶆帓搴忕殑锛岀粡杩囬噸鎺掑簭鍚庡涓嬶細

memory =allocate();    //1锛氬垎閰嶅璞$殑鍐呭瓨绌洪棿 
instance =memory;     //3锛歩nstance鎸囧悜鍒氬垎閰嶇殑鍐呭瓨鍦板潃锛屾鏃跺璞¤繕鏈垵濮嬪寲
ctorInstance(memory);  //2锛氬垵濮嬪寲瀵硅薄

鎸囦护閲嶆帓涔嬪悗锛宨nstance鎸囧悜鍒嗛厤濂界殑鍐呭瓨鏀惧湪浜嗗墠闈紝鑰岃繖娈靛唴瀛樼殑鍒濆鍖栬鎺掑湪浜嗗悗闈€傚湪绾跨▼A鎵ц杩欐璧嬪€艰鍙ワ紝鍦ㄥ垵濮嬪寲鍒嗛厤瀵硅薄涔嬪墠灏卞凡缁忓皢鍏惰祴鍊肩粰instance寮曠敤锛屾伆濂藉彟涓€涓嚎绋嬭繘鍏ユ柟娉曞垽鏂璱nstance寮曠敤涓嶄负null锛岀劧鍚庡氨灏嗗叾杩斿洖浣跨敤锛屽鑷村嚭閿欍€?/p>

volatile瑙e喅閲嶆帓

鐢╲olatile鍏抽敭瀛椾慨楗癷nstance鍙橀噺锛屼娇寰梚nstance鍦ㄨ銆佸啓鎿嶄綔鍓嶅悗閮戒細鎻掑叆鍐呭瓨灞忛殰锛岄伩鍏嶉噸鎺掑簭銆?/p>

public class Singleton3 {
    private static volatile Singleton3 instance = null;
 
    private Singleton3() {}
 
    public static Singleton3 getInstance() {
        if (instance == null) {
            synchronized(Singleton3.class) {
                if (instance == null)
                    instance = new Singleton3();
            }
        }
        return instance;
    }
}

https://www.xamrdz.com/lan/5qk1995658.html

相关文章: