同時擁有兩個或者多個線程,若是程序在單核處理器上運行,多個線程將交替地換入或者換出內存,這些線程是同時「存在」的,每一個線程都處於執行過程當中的某個狀態,若是運行在多核處理器上,此時,程序中的每一個線程都將分配到一個處理器核上,所以能夠同時運行。java
是互聯網分佈式系統架構設計中必須考慮的因素之一,它一般是指,經過設計保證系統可以同時並行處理不少請求。程序員
二者區別:緩存
併發:多個線程操做相同的資源,保證線程安全,合理使用資源。
高併發:服務能同時處理不少請求,提升程序性能。安全
L1,L2,L3級緩存多線程
CUP的頻率太快了,快到主存跟不上,這樣在處理器時鐘週期內,CPU經常須要等待主存,浪費資源。因此緩存Cache的出現,是爲了緩解CPU和內存之間速度的不匹配問題。(結構:CPU->Cache->memory)架構
1)時間局部性:若是某個數據被訪問,那麼在不久的未來它不少能再次被訪問。併發
2)空間局部性:若是某個數據被訪問,那麼與它相鄰的數據很快也可能被訪問。app
M:modify E:Exclusive獨享 S:share I:invalid分佈式
用於保證多個CPU cache之間緩存共享數據的一致。ide
處理器爲提升運算速度而作出違背代碼原有順序的優化。
以下圖所示,線程在棧中,通常新建的本地變量都在堆中。每個在棧中的線程得到的都是堆中的變量、方法的拷貝。
抽象模型:
image
Lock(鎖定)、Unlock(解鎖)、Read(讀取)、Load(載入)、Use(使用)、Assign(賦值)、Store(存儲)、Write(寫入)
若是要把一個變量從主內存中複製到工做內存,就須要按順序地執行read和load操做,若是把變量從工做內存中同步回主內存中,就要按順序地執行store和write操做。但JVM只要求上述操做必須按順序執行,而沒有保證必須是連續執行;
不容許read和load、store和write操做之一單獨出現;
不容許一個線程丟棄它的最近assign的操做,即變量在工做內存中改變了以後必須同步到主存中;
不容許一個線程無緣由地(沒有發生過任何assign操做)把數據從工做內存同步回主內存中;
一個新的變量只能在主存中誕生,不容許在工做內存中直接使用一個未被初始化(load或assign)的變量。即就是對一個變量實施use和store操做以前,必須先執行過了assign和load操做;
一個變量在同一時刻只容許一條線程對其進行lock操做,但lock操做能夠被同一條線程重複執行屢次,屢次執行lock後,只有 執行相同次數的unlock操做,變量纔會被解鎖。lock和unlock必須成對出現;
若是對一個變量執行lock操做,將會清空工做內存中此變量的值,在執行引擎使用這個變量前須要從新執行load或assign操做初始化變量的值。
當多個線程訪問某個類時,無論運行時環境採用何種調度方式或者這些進程將如何交替執行,而且在調試代碼中不須要任何額外的同步或協同,這個類都能表現出正確的行爲,那麼就稱這個類是線程安全的。
原子性:提供了互斥訪問,同一時刻只能有一個線程來對它進行操做;
可見性:一個線程對主內存的修改能夠及時的被其餘線程觀察到;
有序性:一個線程觀察其餘線程中的指令執行順序,因爲指令重排序的存在,該觀察結果通常雜亂無序。
原子性,可見性,有序性:
原子性,通常涉及線程同步的問題;
致使共享變量在線程間不可見的緣由:
線程交叉執行;
重排序結合線程交叉執行;
共享變量更新後的值沒有在工做內存與主存間及時更新。
有序性:
java內存模型中,容許編譯器和處理器對指令進行重排序,可是重排序過程不會影響到單線程程序的執行,卻會影響到多線程併發執行的正確性。
程序次序規則:一個線程內,按照代碼順序,書寫在前面的操做先行發生於書寫在後面的操做;
鎖定規則:一個unlock操做先行發生於後面對同一個鎖的lock操做;
volatile變量規則:對一個變量的寫操做先行發生於後面對這個變量的讀操做;
傳遞規則:若是操做A先行發生於操做B,而操做B又先行發生與操做C,則能夠得出操做A先行發生於操做C;
線程啓動規則:Thread對象的start()方法先行發生於此線程的每個動做;
線程中斷規則:對線程interrupt()方法的調用先行發生於被中斷線程的代碼檢測到中斷事件的發生;
線程終結規則:線程中全部的操做都先行發生於線程的終止檢測,咱們能夠經過Thread.join()方法結束、Thread.isAlive()的返回手段檢測到線程已經終止執行;
對象終結規則:一個對象的初始化完成先行發生於他的finalize()方法的開始。
感謝你們看到這裏,若是本文有什麼不足之處,歡迎多多指教;若是你以爲對你有幫助,請給我點個贊。
也歡迎你們關注個人公衆號:程序員麥冬