多線程理解2

多線程:
        多線程的同步:       
                多線程併發訪問同一個對象(臨界資源),如果不對線程進行同步控制,破壞了原子操作(不可再分的操作),則會造成臨界資源(兩個線程同時訪問的資源)的數據不一致。   

                每一個對象都有一個互斥的鎖標記和一個鎖池。當線程擁有這個對象的鎖標記時才能訪問這個資源,沒有鎖標記便進入鎖池,保證在同步代碼塊中只有一個線程,解決了多線程同步控制的問題。
               
                關鍵字:synchronized        //線程在同步代碼中必須採用串行訪問
                        synchronized修飾代碼塊:對括號內的對象object加鎖,只有拿到對象鎖標記的線程才能進入該代碼塊。
                                   public void push(char c){
                                        synchronized(object){         //object只要是對象就可以,但必須保證是同一對象
                                                ……
                                                同步代碼
                                                ……
                                        }
                                   }
                                  
                        synchronized修飾方法:在整個方法範圍內對當前對象的加鎖,只有拿到對象鎖標記的線程才能執行該方法。儘可能的少用
                                   public synchronized void push(char c) {
                                        ……
                                        同步代碼
                                        ……       
                                }
                                      一個線程可以同時擁有多個對象的鎖標記,鎖標記如果過多,就會出現線程等待其他線程釋放鎖標記,而又都不釋放自己的鎖標記供其他線程運行的狀況,造成死鎖。                               

                靜態方法可以是同步方法:但是它所鎖的並不是當前對象,是類對象。
                抽象方法不能是synchronized同步的方法。
                構造方法不能是synchronized同步的方法。
                       
                線程因爲未拿到鎖標記而發生阻塞進入鎖池(lock pool)。每個對象都有自己的一個鎖池的空間,用於放置等待運行的線程。由系統決定哪個線程拿到鎖標記並運行
               
                利用Collections類中的synchronizedXxxx(Xxxx ss)方法可以得到相應集合的線程安全的集合
               
                注意:
                        在同步語句塊中不能直接操作對象鎖正在使用的對象。
                        對象與鎖一一對應。
                        同步依賴對象鎖,鎖對象相同,同步語句串行,鎖對象不同,同步語句並行。
                        順序鎖,不要回調,反向打開。
                        能不用同步就不用同步,有數據共享衝突時才使用同步。
               
        等待通知機制:
                線程間通信使用的空間稱之爲對象的等待對列(wait pool),該隊列也是屬於對象的空間的。
               
                使用Object類中wait()的方法,在運行狀態中,線程調用wait(),此時表示線程將釋放自己所有的鎖標記和CPU的佔用,同時進入這個對象的等待池。等待池的狀態也是阻塞狀態,只不過線程釋放自己的鎖標記。只有在對該對象加鎖的同步代碼塊裏,才能掉用該對象的wait(),表示線程將會釋放所有鎖標記,進入等待隊列,線程將進入等待隊列狀態。  一個線程進入了一個對對象加鎖的同步代碼塊,並對該對象調用了wait()方法,釋放自己擁有的所有鎖標記,進入該對象等待隊列,另一個線程獲得了該對象的鎖標記,進入代碼塊對該對象調用了notify()方法,就會從等待隊列裏釋放出一線程,釋放出的這個線程要繼續運行就還要進入那個同步代碼塊,因爲得不到要訪問代碼塊對象的鎖標記,而進入該對象的鎖池,等待鎖標記釋放。
               
                什麼情況下釋放鎖:
                        同類代碼執行完畢。
                        異常未處理,錯誤退出。
                        調用wait()。
               
                相關方法:
                        1) wait():交出鎖和CPU的佔用;
                        2) notify():將從對象的等待池中移走一個任意的線程,並放到鎖池中,那裏的對象一直在等待,直到可以獲得對象的鎖標記。
                        3) notifyAll(): 將從等待池中移走所有等待那個對象的線程並放到鎖池中,只有鎖池中的線程能獲取對象的鎖標記,鎖標記允許線程從上次因調用wait()而中斷的地方開始繼續運行
                       
                注意:
                        用notifyAll()取代notify(),因爲在調用notify()方法時,是由系統決定釋放出哪個線程。
                        只能對加鎖的資源進行wait()和notify()。
                        判斷是否進行等待wait()時,用while代替if來進行判斷。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章