[英]What is the difference between volatile and synchronized?
我正在嘗試查看volatile
在這里如何工作。 如果我將cc
聲明為volatile
,則輸出如下。 我知道線程執行輸出時間不同時間,但我讀的地方, volatile
是一樣synchronized
,所以為什么我得到這個輸出? 如果我使用Thread1
兩個實例,那有關系嗎?
2Thread-0 2Thread-1 4Thread-1 3Thread-0 5Thread-1 6Thread-0 7Thread-1 8Thread-0 9Thread-1 10Thread-0 11Thread-1 12Thread-0
public class Volexample {
int cc=0;
public static void main(String[] args) {
Volexample ve=new Volexample();
CountClass count =ve.new CountClass();
Thread1 t1=ve.new Thread1(count);
Thread2 t2=ve.new Thread2(count);
t1.start();
t2.start();
}
class Thread1 extends Thread{
CountClass count =new CountClass();
Thread1(CountClass count ){
this.count=count;
}
@Override
public void run() {
/*for(int i=0;i<=5;i++)
count.countUp();*/
for(int i=0;i<=5;i++){
cc++;
System.out.println(cc + Thread.currentThread().getName());
}
}
}
class Thread2 extends Thread {
CountClass count =new CountClass();
Thread2(CountClass count ){
this.count=count;
}
@Override
public void run(){
/*for(int i=0;i<=5;i++)
count.countUp();*/
for(int i=0;i<=5;i++){
cc++;
System.out.println(cc + Thread.currentThread().getName());
}
}
}
class CountClass{
volatile int count=0;
void countUp(){
count++;
System.out.println(count + Thread.currentThread().getName());
}
}
}
在Java中, volatile
關鍵字的語義定義得很好。 它們確保其他線程將看到對變量的最新更改。 但是它們不會使讀取-修改-寫入操作成為原子操作。
因此,如果i
是volatile
而您使用i++
,則可以保證讀取i
的最新值,並且可以保證其他線程會立即看到您對i
的寫入,但是不能保證兩個線程不會交錯讀取它們。 / modify / write操作,以便兩個增量具有單個增量的效果。
假設i
是一個易失性整數,其值初始化為零,除此以外沒有寫操作,並且有兩個線程執行i++;
,可能會發生以下情況:
i
的最新值。 i
的最新值。 i
。 i
。 i
的最新值是1,因此現在訪問i
任何線程都將看到1。 請注意,即使每個線程始終讀取任何其他線程寫入的最新值,增量也會丟失。 volatile
關鍵字提供可見性,而不是原子性。
您可以使用synchronized
來形成復雜的原子操作。 如果只需要簡單的類,則可以使用Java提供的各種Atomic*
類。
Java volatile
關鍵字用於將Java變量標記為“正在存儲在主存儲器中”。 這意味着,對易失性變量的每次讀取都將從計算機的主內存中讀取,而不是從緩存中讀取,對易失性變量的每次寫入都將被寫入主內存中,而不僅是高速緩存。
它保證您正在訪問此變量的最新值。
PS使用較大的循環來發現錯誤。 例如,嘗試迭代10e9次。
使用volatile的用例是從映射到設備寄存器的內存中讀取/寫入,例如在微控制器上,其中CPU以外的其他東西正在向該“內存”地址讀取/寫入值,因此編譯器不應將變量優化掉。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.