回顧:
我們到web階段的程序都是多線程,web下的項目都是多線程環(huán)境
會創(chuàng)建一個.class類,同時開辟多個線程,同時使用,由web服務器自動做
Thread有四個方法:
兩個成員方法:getName(),獲取線程名稱
setName()設置線程名稱
兩個靜態(tài)方法:
currentThread()獲取當前線程對象
sleep()讓當前線程暫停指定的毫秒值
多線程的運行原理:
兩個線程一起工作,兩個線程會無序運行,
常見的高并發(fā)的線程安全性問題:
變量的可見性:一個線程的訪問頻率太快,他如果訪問速度太快,會從方法區(qū)加載到自己的main棧方法單獨做一個副本,不會再去方法區(qū)找變量,會導致,方法區(qū)內的變量更改,此線程也沒變化.
代碼的有序性:代碼重排的問題,一段代碼,JVM編譯器再編譯的時候,為了提高效率,在不影響執(zhí)行結果的情況下,可能會對代碼進行重排,在多線程的環(huán)境下,就會出現問題,導致結果不一樣.
變量訪問的原子性: 多個線程共同訪問同一變量,由于訪問的代碼不具有原子性(不可再拆分的),說一導致最終結果不準確.
原子性:在java中,對基本數據類型的變量和賦值操作都是原子性操作
j=i;是兩個操作,讀取i,將i賦值給j
i++;是三個操作,讀取i值,i+1;將+1的結果賦值給i
在單線程環(huán)境中,我們可以認為整個步驟都是原子性操作,但在多線程環(huán)境下,Java
只保證了基本數據類型的變量和賦值操作才是原子性(在32位的jdk環(huán)境下,對64位數據的操作不是原子性操作,如long,double)
https://blog.csdn.net/u013412772/article/details/80109727
cas機制,樂觀鎖會先取這個值,交給cas的一個方法,告訴他我要把這個值變成另外的一個值
所以cas方法做這個事,先比較,會從內存中先把值取出來,去跟你要改的值進行比較,如果一樣,執(zhí)行修改,不一樣就自旋,再取一次,再去比較,樂觀鎖,
對數組進行操作的原子類,AtomicIntegerArray,int類型數據進行原子操作
AtomicLongArray,對Long[]數據進行原子操作
AtomicReferenceArray,對引用類型數組原子操作
在多線程環(huán)境下,這三個問題要全部解決,才是一個好的解決方案,第三方的線程框架,這些框架提出的解決方案,java類庫提出的解決方案就是原子類
web項目默認多線程環(huán)境
,需要了解的:線程安全
正式學習:
synchronized(同步)關鍵字:對一段代碼
作用:我們對一段代碼或者一個方法整體的進行多線程安全的控制,它代表同步的,可以保證單個線程在執(zhí)行這段代碼時,其他的線程不能執(zhí)行這段代碼,要排隊等待
使用方式:
同步代碼塊:
同步方法(常用)
同步代碼塊:需要同一個共享的鎖對象,需要靜態(tài)的,普通對象,不共享.
使用結構:繼承Thread類,重寫run()方法,在run方法內寫synchronized(共享的對象,需要時static修飾的){
代碼塊
}
一個線程搶到鎖了之后,釋放鎖的時候,還繼續(xù)參與搶鎖
synchronized可以鎖run放在重寫run方法的void之前,自定義MyThread對象實現Runable接口,并且在測試類中,new一個自定義對象,再使用自定義對象來作為Thread的有參方法,再使用Thread的start方法
同步方法:將一個方法整體設置為同步的,使用synchronized關鍵字
格式:
自定義類繼承Thread類,方法為public static synchronized 返回值類型 方法名(形參列表){? }
static的原因是:普通成員方法的鎖對象是:本對象
靜態(tài)方法的鎖對象是本類的Class對象,JVM會為每一個類創(chuàng)建一個class對象,加上靜態(tài)的關鍵字
測試時,需要new多個自定義類,給自定義類setname(""),再start()
實現Runnable接口的synichronized關鍵字的使用方式
Thread.currentThread().getName(),獲取當前的線程對象的線程名
自定義類實現Runnable接口,方法可以不使用static關鍵字修飾,,測試類中只需要new一個自定義類,再通過new Thread(自定義類名)的有參構造方法來創(chuàng)建多個線程
也可以synchronized修飾run方法,
synchronized被稱為悲觀鎖:無論是否有線程安全,都會加鎖,就會有額外的操作,就會降低效率
CAS機制,被稱為"樂觀鎖",比較并交換,"比較"的大部分時候都是線程安全的.針對少數發(fā)生線程安全問題時,才采用"自旋",再JDK1.5之后的JUC包(java.util.concurrent包)中的很多原子類,同步類,都是使用CAS機制實現,比較快
Lock鎖:提供了一種新的鎖:java.util.concurrent.Lock(接口),使用方法的形式進行枷鎖,釋放鎖,比synchronized更加靈活,
Lock鎖的內部tong'bu'dia'a'm
CopyOnWriteArrayList類(線程安全的)
CopyOnWriteArraySet類
ConcurrentHashMap類
多線程控制的工具類:
CountDownLatch多線程協(xié)作
CyclicBarrier多線程協(xié)作
Semaphore并發(fā)數量控制
Exchanger線程信息交互
synchronized,我們相對一段代碼或者一個方法進行多線程安全的控制,
她表示同步的,可以保證一個線程在使用這端代碼或者這個方法是,其他線程不能執(zhí)行這段代碼
要排隊等待
使用方式:同步代碼塊? ? 同步方法(常用)
同步代碼塊:方法(){
synchronized(鎖對象){
}
}
他必須是一個對象,任何對象都可以,但必須保證多個線程共享同一個鎖對象
普通成員方法:鎖對象是本對象
靜態(tài)方法=>鎖對象:本類的class對象