java并发编程笔记_java并发编程笔记(一)——并发编程简介
java并發(fā)編程筆記(一)——簡(jiǎn)介
線程不安全的類示例
public class CountExample1 {
// 請(qǐng)求總數(shù)
public static int clientTotal = 5000;
// 同時(shí)并發(fā)執(zhí)行的線程數(shù)
public static int threadTotal = 200;
public static int count = 0;
public static void main(String[] args) throws Exception {
ExecutorService executorService = Executors.newCachedThreadPool();
final Semaphore semaphore = new Semaphore(threadTotal);
final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
for (int i = 0; i < clientTotal ; i++) {
executorService.execute(() -> {
try {
semaphore.acquire();
add();
semaphore.release();
} catch (Exception e) {
log.error("exception", e);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executorService.shutdown();
log.info("count:{}", count); //最終得到的結(jié)果是小于5000的
}
private static void add() {
count++;
}
}
并發(fā):
同時(shí)擁有兩個(gè)或者多個(gè)線程,如果程序在單核處理器上運(yùn)行,多個(gè)線程將交替的換入換出內(nèi)存,這些線程是同時(shí)“存在”的,每個(gè)線程都處于執(zhí)行過程中的某個(gè)狀態(tài),如果運(yùn)行在多核處理器上,程序中的每個(gè)線程都將分配到一個(gè)處理器核上,因此可以同時(shí)運(yùn)行。
多個(gè)線程操作相同的資源,保證線程安全,合理使用資源
高并發(fā)(High Concurrency):
高并發(fā)是互聯(lián)網(wǎng)分布式系統(tǒng)架構(gòu)設(shè)計(jì)中必須考慮的因素之一,它通常是指,通過設(shè)計(jì)保證系統(tǒng)能夠同時(shí)并行處理很多請(qǐng)求。
java 內(nèi)存模型(Java Memory Model,JMM)
java堆
可以在運(yùn)行時(shí)動(dòng)態(tài)的分配內(nèi)存大小;
由于在運(yùn)行時(shí)動(dòng)態(tài)的分配大小,所以他的存取速度很慢;
java棧
存取速度很快,僅次于計(jì)算機(jī)的寄存器,棧里的數(shù)據(jù)都是可以共享的;
棧由于存放的數(shù)據(jù)大小與生存期是要求確定的,所以缺少一定的靈活性;
java線程引用對(duì)象的圖示
cpu訪問主存圖示
當(dāng)兩個(gè)線程同時(shí)訪問一個(gè)對(duì)象時(shí),這兩個(gè)線程持有的是這個(gè)對(duì)象的私有拷貝。
cpu模型圖
cpu訪問寄存器的速度遠(yuǎn)大于在主存上的讀取速度
由于計(jì)算機(jī)的存儲(chǔ)設(shè)備與處理器的處理速度有好幾個(gè)數(shù)據(jù)量級(jí)的差距,所以存在了高速緩存區(qū)
java內(nèi)存模型抽象結(jié)構(gòu)圖
java內(nèi)存模型-同步八種操作
lock(鎖定):作用于主內(nèi)存的變量,把一個(gè)變量標(biāo)識(shí)為一條線程獨(dú)占狀態(tài)
unlock(解鎖):作用于主內(nèi)存的變量,把一個(gè)處于鎖定狀態(tài)的變量釋放出來(lái),釋放后的變量才可以被其他線程鎖定
read(讀取):作用主內(nèi)存的變量,把一個(gè)變量值由主內(nèi)存?zhèn)鬏數(shù)骄€程的工作內(nèi)存中,以便隨后的load使用
load(載入):作用于工作內(nèi)存的變量,它把read操作從主內(nèi)存中得到的變量值放入工作內(nèi)存的變量副本中
use(使用):作用于工作內(nèi)存的變量,把工作內(nèi)存中的一個(gè)變量值傳遞給執(zhí)行引擎
assign(賦值):作用于工作內(nèi)存的變量,它把一個(gè)從執(zhí)行引擎接收到的值賦值給工作內(nèi)存的變量
store(存儲(chǔ)):作用于工作內(nèi)存的變量,把工作內(nèi)存中的一個(gè)變量的值傳送到主存中,以便隨后的write的操作
write(寫入):作用于主內(nèi)存的變量,它把store操作從工作內(nèi)存中一個(gè)變量的值傳送到主內(nèi)存的變量中
java內(nèi)存模型-同步規(guī)則
如果要把一個(gè)變量從主存中復(fù)制到工作內(nèi)存,就需要按順序的執(zhí)行read和load操作,如果把變量從工作內(nèi)存中同步回主內(nèi)存中,就要按順序的執(zhí)行store和write操作。但java內(nèi)存模型只要求上述操作必須按順序執(zhí)行,而沒有保證必須是連續(xù)執(zhí)行
不允許read和load、store和write操作之一單獨(dú)出現(xiàn)
不允許一個(gè)線程丟棄它的最近assign的操作,即變量在工作內(nèi)存中改變了之后,必須同步到主內(nèi)存中
不允許一個(gè)線程無(wú)原因的(沒有發(fā)生過任何assign操作)把數(shù)據(jù)從工作內(nèi)存同步回主內(nèi)存中
一個(gè)新的變量只能在主內(nèi)存中誕生,不允許在工作內(nèi)存中直接使用一個(gè)未被初始化(load和assign)的變量。即就是對(duì)一個(gè)變量實(shí)施use和store操作之前,必須先執(zhí)行過了assign和load操作
一個(gè)變量在同一時(shí)刻只允許一條線程對(duì)其進(jìn)行l(wèi)ock操作,但lock操作可以被同一條線程重復(fù)執(zhí)行多次,多次執(zhí)行l(wèi)ock后,只有執(zhí)行相同次數(shù)的unlock操作,變量才會(huì)被解鎖,lock和unlock必須成對(duì)出現(xiàn)
如果對(duì)一個(gè)變量執(zhí)行l(wèi)ock操作,將會(huì)清空工作內(nèi)存中此變量的值,在執(zhí)行引擎使用這個(gè)變量前需要重新執(zhí)行l(wèi)oad或assign操作初始化變量的值
如果一個(gè)變量事先沒有被lock操作鎖定,則不允許對(duì)它執(zhí)行unlock操作,也不允許去unlock一個(gè)被其他線程鎖定的變量
對(duì)一個(gè)變量執(zhí)行unlock操作之前,必須先把此變量同步到主內(nèi)存中(執(zhí)行store和write操作)
并發(fā)的優(yōu)勢(shì)和風(fēng)險(xiǎn)
優(yōu)勢(shì)
同時(shí)處理多個(gè)請(qǐng)求,響應(yīng)更快,負(fù)責(zé)的操作可以分成多個(gè)進(jìn)程同時(shí)進(jìn)行
程序設(shè)計(jì)在某些情況下更簡(jiǎn)單,也可以有更多的選擇
CPU能夠在等待IO的時(shí)候做一些其他的事情
風(fēng)險(xiǎn)
多個(gè)線程共享數(shù)據(jù)可能會(huì)產(chǎn)生與期望不相符的結(jié)果
某個(gè)操作無(wú)法繼續(xù)進(jìn)行下去時(shí),就會(huì)發(fā)生活躍性問題,比如死鎖、饑餓等問題
線程過多時(shí)會(huì)使得CPU頻繁切換,調(diào)度時(shí)間增多,同步至機(jī)制;消耗過多內(nèi)存
總結(jié)
CPU多級(jí)緩存:緩存一致性,亂序執(zhí)行優(yōu)化
java內(nèi)存模型:JMM規(guī)定、抽象結(jié)構(gòu)、同步八中操作及規(guī)則
java并發(fā)的優(yōu)勢(shì)與風(fēng)險(xiǎn)
總結(jié)
以上是生活随笔為你收集整理的java并发编程笔记_java并发编程笔记(一)——并发编程简介的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 战魂铭人马甲裙怎么获得
- 下一篇: 逻辑短路 java_逻辑操作符中的短路现