1. 程式人生 > >Java基礎複習一之多執行緒(併發,記憶體模型)

Java基礎複習一之多執行緒(併發,記憶體模型)

前言:畢業來北京轉眼一年半了,但是沒有太多的成績。沒有太多的記錄和沉澱。現在開始複習一下基礎的知識。涉及到的有多執行緒,集合,JVM,NIO,資料庫,作業系統。後面還是想走實時處理那一塊,可能會有那方面的研究。

多執行緒:為啥用?因為想去執行不同的任務,或利用現狀多核的處理器。而因為執行緒相較於程序輕量級。

執行緒之間可以共享一個變數和資源,一起訪問某個資源,所以有了併發(同步發生)。但為了訪問的秩序(執行緒安全)呢,所以有了同步(執行緒在資源前排隊,需要鎖)。為了實現更高階的執行緒一些功能,多個執行緒之間互動,所以有了訊號量

++++同步:

在java語言中同步很直接的就是:synchronized 同步標誌,實際就是取得鎖的過程。

synchronized修飾普通方法= synchronized(this){程式碼塊},物件鎖,監視器 synchronized修飾靜態方法= synchronized(A.class){程式碼塊},類鎖 (synchronized修飾Thread的RUN和unable的RUN,一個是普通,一個是靜態(其他執行緒同步)。) synchronized用到了鎖,鎖保證了互斥(mutual exclusion) 和可見性(visibility)。每次只能有一個執行緒持有鎖。當前鎖修改的共享變了,下個進入鎖的執行緒可以看到。 程式碼塊的範圍可以更細一點。 volatile可以用在任何變數前面(final除外)。保證了可見性。

++++執行緒通訊: 因為有了同步,用了鎖,那麼呢問題來了,我想退出鎖,怎麼通知其他人,我要退出了呢,所以有了訊號量。JAVA的物件呢,既可以當鎖用,又可以當訊號量,所以在同步的方法中,通過:this.wait(); / this.notify();  一個等待被喚醒,一個通知其他的執行緒可以來排隊了。 好像synchronized可以解決所有同步加鎖的問題了,但是,預設用物件的鎖,畢竟只有一個,如果我認為一個JAVA物件對應N(N>1)個鎖怎麼辦呢?其實用最原生的鎖物件不就OK了?,之前的訊號量,也可以通過鎖物件來構造(同理可以多個) --這段理解有誤,synchronized、volatile
只是關鍵字,而LOCK是物件,更高階一點,提供了更高階的功能。try獲取鎖、 公平鎖等。還可以通過不同的條件,來讓不同執行緒,等待不同的條件。
    final Lock lock = new ReentrantLock();
    final Condition notFull  = lock.newCondition(); 
    final Condition notEmpty = lock.newCondition();
這裡稍微不同:lock.lock() /unlock() 注意用 finally 。notFull.await()/notFull.notify() 說到訊號量再講講執行緒間通訊的另一種:管道。管道相連。一個讀,一個寫。堵塞佇列也可以實現。 ++++執行緒控制: JAVA併發包裡有一些併發控制的類。這個是高階於:synchronized,volatile(低階) LOCK(中級)的 CountDownLatch 門插銷計數器:對一個執行緒用此物件等待方法,其他執行緒,物件countDown()每次減一;減到0喚起await的執行緒。 CycliBarrier. 等所有執行緒都達到一個起跑線後才能開始繼續執行。

+++++併發集合

JAVA原生的集合都是fast-fail的,為了在多執行緒下,同步的使用集合有了一些整合好的併發集合。

ConcurrentHashMap:鎖分離技術,在HASH之前有SEGMENT層,每個段上加鎖。

++++非阻塞方式合集 volatile關鍵字時非阻塞的,但是對同步支援不完全。所以JAVA自己實現了一下常用的非阻塞的執行緒安全的變數,都是利用了硬體的CAS特性來完成,可以說利用硬體保證了原子性。(鎖都是阻塞的,將讀-改-存 原子操作化) AtomicBoolean、AtomicInteger、AtomicReference
提供對陣列型別的變數進行處理的Java類,AtomicIntegerArray、AtomicLongArray和AtomicReferenceArray類。(同上,只是放在類數組裡,呼叫時也只是多了一個操作元素索引的引數)
++++以上都是可以使用物件,鎖來控制多執行緒併發訪問。後面講講記憶體模型和一些關鍵字:final,volatile. 抽象的講,多個執行緒間有共享 的記憶體,也有自己的本地記憶體(抽象出CPU快取暫存器快取等的地方)-(考慮可見性)-。JAVA一條語句可能會被拆分成多條指令(考慮非原子性),指令之間也可能會被調優導致重新排序(重排序)。 final 指的是不可變的,只能初始化一次,這樣的話,在多執行緒中就不會有執行緒安全的問題。 參考: http://blog.csdn.net/escaflone/article/details/10418651 http://www.ibm.com/developerworks/cn/java/j-jtp06197.html
http://www.journaldev.com/1037/java-thread-wait-notify-and-notifyall-example