一、volatile介紹
volatile是一個類型修飾符(type specifier),就像大家更熟悉的const一樣,它是被設(shè)計用來修飾被不同線程訪問和修改的變量。volatile的作用是作為指令關(guān)鍵字,確保本條指令不會因編譯器的優(yōu)化而省略,且要求每次直接讀值。volatile的變量是說這變量可能會被意想不到地改變,這樣,編譯器就不會去假設(shè)這個變量的值了。
volatile作用:
簡單地說就是防止編譯器對代碼進行優(yōu)化。比如如下程序:
4XBYTE[2]=0x55;
XBYTE[2]=0x56;
XBYTE[2]=0x57;
XBYTE[2]=0x58;
對外部硬件而言,上述四條語句分別表示不同的操作,會產(chǎn)生四種不同的動作,但是編譯器卻會對上述四條語句進行優(yōu)化,認(rèn)為只有XBYTE[2]=0x58(即忽略前三條語句,只產(chǎn)生一條機器代碼)。如果鍵入volatile,則編譯器會逐一地進行編譯并產(chǎn)生相應(yīng)的機器代碼(產(chǎn)生四條代碼)。
正確使用volatile變量的條件:
只能在有限的一些情形下使用 volatile變量替代鎖。要使 volatile變量提供理想的線程安全,必須同時滿足下面兩個條件:
● 對變量的寫操作不依賴于當(dāng)前值。
● 該變量沒有包含在具有其他變量的不變式中。
實際上,這些條件表明,可以被寫入 volatile變量的這些有效值獨立于任何程序的狀態(tài),包括變量的當(dāng)前狀態(tài)。
第一個條件的限制使 volatile變量不能用作線程安全計數(shù)器。雖然增量操作(x++)看上去類似一個單獨操作,實際上它是一個由讀取-修改-寫入操作序列組成的組合操作,必須以原子方式執(zhí)行,而 volatile 不能提供必須的原子特性。實現(xiàn)正確的操作需要使 x 的值在操作期間保持不變,而 volatile變量無法實現(xiàn)這點。(然而,如果將值調(diào)整為只從單個線程寫入,那么可以忽略第一個條件。)
大多數(shù)編程情形都會與這兩個條件的其中之一沖突,使得 volatile變量不能像 synchronized 那樣普遍適用于實現(xiàn)線程安全。清單 1 顯示了一個非線程安全的數(shù)值范圍類。它包含了一個不變式 —— 下界總是小于或等于上界。
二、多線程的介紹
多線程(英語:multithreading),是指從軟件或者硬件上實現(xiàn)多個線程并發(fā)執(zhí)行的技術(shù)。具有多線程能力的計算機因有硬件支持而能夠在同一時間執(zhí)行多于一個線程,進而提升整體處理性能。具有這種能力的系統(tǒng)包括對稱多處理機、多核心處理器以及芯片級多處理(Chip-level multithreading)或同時多線程(Simultaneous multithreading)處理器。[1] 在一個程序中,這些獨立運行的程序片段叫作“線程”(Thread),利用它編程的概念就叫作“多線程處理(Multithreading)”。具有多線程能力的計算機因有硬件支持而能夠在同一時間執(zhí)行多于一個線程(***譯作“執(zhí)行緒”),進而提升整體處理性能。
多線程用途:
用途在大多數(shù)研究領(lǐng)域內(nèi)是要求線程調(diào)度程序要能夠快速選擇其中一個已就緒線程去運行,而不是一個一個運行而降低效率。所以要讓調(diào)度程序去分辨線程的優(yōu)先級是很重要的。而線程調(diào)度程序可能是以硬件、軟件,或是軟硬件并存的形式存在。
多線程的優(yōu)點:
使用線程可以把占據(jù)時間長的程序中的任務(wù)放到后臺去處理
用戶界面可以更加吸引人,這樣比如用戶點擊了一個按鈕去觸發(fā)某些事件的處理,可以彈出一個進度條來顯示處理的進度·
程序的運行速度可能加快
在一些等待的任務(wù)實現(xiàn)上如用戶輸入、文件讀寫和網(wǎng)絡(luò)收發(fā)數(shù)據(jù)等,線程就比較有用了。在這種情況下可以釋放一些珍貴的資源如內(nèi)存占用等等
多線程技術(shù)在IOS軟件開發(fā)中也有舉足輕重的位置
多線程的缺點:
如果有大量的線程,會影響性能,因為操作系統(tǒng)需要在它們之間切換。
更多的線程需要更多的內(nèi)存空間。
線程可能會給程序帶來更多“bug”,因此要小心使用。
線程的中止需要考慮其對程序運行的影響。
通常塊模型數(shù)據(jù)是在多個線程間共享的,需要防止線程死鎖情況的發(fā)生。
三、多線程中volatile使用的理解
package com.casking.cdds.modules.test.web;
public class Counter {
//volatile關(guān)鍵字能保證多個內(nèi)存塊中的引用值是最新的可見性,不能保證原子性。可見性只能保證每次讀取的是最新的值,但是volatile沒辦法保證對變量的操作的原子性。
public volatile static int count = 0;
public synchronized static void inc() {
// 這里延遲1秒,使得結(jié)果明顯
try {
Thread.sleep(1);
} catch (InterruptedException e) {
}
count++;
}
public static void main(String[] args) {
// 同時啟動1000個線程,去進行i++計算,看看實際結(jié)果
for (int i = 0; i 《 1000; i++) {
new Thread(new Runnable() {
@Override
public void run() {
Counter.inc();
}
}).start();
}
// 方法返回活動線程的當(dāng)前線程的線程組中的數(shù)量---主線程下
while (Thread.activeCount() 》 1) // 保證前面的線程都執(zhí)行完
Thread.yield(); //當(dāng)一個線程使用了這個方法之后,它就會把自己CPU執(zhí)行的時間讓掉,讓自己或者其它的線程運行。
// 這里每次運行的值都有可能不同,可能為1000
System.out.println(“運行結(jié)果:Counter.count=” + Counter.count);
}
}
評論
查看更多