深刻理解java虛擬機:java
一、java內存模型數據庫
java虛擬機規範中試圖定義一種Java內存模型。Java Memory Model(JMM)安全
1.1 主內存與工做內存多線程
java內存模型規定全部的變量都存儲在主內存中(Main Memory)中。併發
每一個線程還有本身的工做內存(working Memory),線程的工做內存保存了該線程使用到的變量的主內存副本拷貝,線程對變量的操做都在工做內存中,而不能直接讀寫主內存中的變量。性能
1.2 內存見交互操做優化
1.3 volatile變量的特殊規則spa
保證對全部線程有可見性操作系統
禁止指令重排優化線程
1.4對於long和double型變量的特殊規則
JMM要求1.2中的8個操做具備原子性,可是對於64位數據類型(long double)
容許虛擬機將沒有被volatile修飾的64位數據的讀寫操做劃分爲兩次32位的操做來進行。
即不保證64位數據類型 load store read write這4個操做的原子性。
全部當有多個線程共享未聲明位volatile的long或double類型的變量,某些線程就會讀到「半個變量」的數值。
1.5 原子性 可見性 有序性
原子性:read,load,assign,use,write,synchronized之間的操做
可見性:當一個線程修改了某個變量,其餘線程可以馬上得知這個修改。
volatile,synchronized,final均有可見性
同步塊的的可見性在於,一個變量執行unlock以前,必須先把此變量同步回主內存中。
有序性:若是在本線程中觀察,全部的操做都是有序的。若是在一個線程中觀察另外一個線程,全部操做都是無序的。
前半句是指:線程內表現爲串行語義
後半句是指:指令重排,工做內存與主內存同步延遲
1.6 先行發生原則
時間前後順序與先行發生原則之間基本沒有太大關係,因此當咱們衡量併發安全問題的時候不要收到時間順序的干擾,一切必須按照先行發生原則爲準。
2 Java與線程
2.1 線程的實現
線程式比進程更輕量級的調度執行單位,線程的引入,能夠把一個進程的資源分配和執行調度分開,各個線程既能夠共享進程資源(內存地址,文件I?O),又能夠獨立調度。(線程式CPU調度的基本單位)
實現線程有三種方法:
一、使用內核線程實現
內核線程 Kernel-level Thread,KLT 直接由操做系統內(Kernel)支持的線程。內核經過操縱調度器(Scheduler)對線程進行調度,並將線程的任務映射到各個處理器上。
支持多線程的內核叫多線程內核 multi-Threads kernel
程序不會直接使用內核線程,並且使用內核線程的一種高級接口---輕量級進程 Light Weight Process LWP
因爲內核線程的支持,每一個輕量級進程都成爲一個獨立的調度單位,及時有一個輕量進程在系統中阻塞,也不會影響到整個進程的工做。
侷限性:基於內核線程實現,各類線程操做,例如建立,析構及同步,都須要進行系統調用。
系統調用的代價享隊較高,須要在用戶態(User Mode)和內核態(Kernel Mode)中來回切換。其次,輕量進程須要下號必定的內核資源,所以一個系統支持輕量級進程的數量是有限的。
二、使用用戶線程實現
廣義上來說,一個線程只要不是內核線程,就能夠認爲是用戶線程(User Thread),從這個定義來說,輕量級進程也屬於用戶進程。
狹義上用戶線程指的是徹底創建在用戶空間的線程庫上,系統內核不能感知線程存在的實現。
若是程序實現得當,這種線程不須要切換到內核態,所以操做能夠是很是快速且低消耗的,也能夠支持規模更大的線程數量,部分高性能數據庫中的多線程就是有用戶線程實現的。
因爲操做系統只能把處理器資源分配到進程,諸如「阻塞如何處理」,「多處理器系統中如何將線程映射到到其餘處理器」,這類問題解決起來異常困難,甚至不可完成。
於是使用用戶線程實現的程序通常都比較複雜。
3.使用用戶線程加輕量級進程混合實現
操做系統提供支持的輕量級進程做爲用戶線程和內核線程之間的橋樑,這樣內核提供的線程調度功能及處理器映射,而且用戶線程的系統調用要經過輕量級線程來完成,下降整個進程被徹底阻塞的風險。
用戶線程與輕量級進程的數目比也不必定 N:M
2.二、Java線程的實現
2.三、java線程調度
線程調度是指系統爲線程分配處理器使用權的過程
協同式線程調度
搶佔式線程調度
Java線程調度式系統自動完成的,可是建議給線程設置優先級。
狀態轉換:
Waiting:處於這個狀態的線程不會被分配CPU執行時間,他們要等待被其餘線程顯示地喚醒。
Timed Waiting:處於這個狀態的線程不會被分配CPU執行時間,無須等待其餘線程顯示喚醒。在必定時間以後會由系統自動喚醒。
Blocked(阻塞):程序等待進入同步區域的時候,線程處於這種狀態。