Java基礎複習一之多執行緒(併發,記憶體模型)
阿新 • • 發佈:2018-12-26
前言:畢業來北京轉眼一年半了,但是沒有太多的成績。沒有太多的記錄和沉澱。現在開始複習一下基礎的知識。涉及到的有多執行緒,集合,JVM,NIO,資料庫,作業系統。後面還是想走實時處理那一塊,可能會有那方面的研究。
多執行緒:為啥用?因為想去執行不同的任務,或利用現狀多核的處理器。而因為執行緒相較於程序輕量級。
執行緒之間可以共享一個變數和資源,一起訪問某個資源,所以有了併發(同步發生)。但為了訪問的秩序(執行緒安全)呢,所以有了同步(執行緒在資源前排隊,需要鎖)。為了實現更高階的執行緒一些功能,多個執行緒之間互動,所以有了訊號量。
++++同步:
在java語言中同步很直接的就是:synchronized 同步標誌,實際就是取得鎖的過程。
++++執行緒通訊: 因為有了同步,用了鎖,那麼呢問題來了,我想退出鎖,怎麼通知其他人,我要退出了呢,所以有了訊號量。JAVA的物件呢,既可以當鎖用,又可以當訊號量,所以在同步的方法中,通過:this.wait(); / this.notify(); 一個等待被喚醒,一個通知其他的執行緒可以來排隊了。 好像synchronized可以解決所有同步加鎖的問題了,但是,預設用物件的鎖,畢竟只有一個,如果我認為一個JAVA物件對應N(N>1)個鎖怎麼辦呢?其實用最原生的鎖物件不就OK了?,之前的訊號量,也可以通過鎖物件來構造(同理可以多個) --這段理解有誤,synchronized、volatile
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