天天看點

java volatile atomic_java中volatile和AtomicInteger

一:AtomicInteger

publicclassContentType

{

publicstaticAtomicInteger ai=

newAtomicInteger(0);

publicstaticvoidmain(String[]

args) throwsInterruptedException {

finalCountDownLatch latch=

newCountDownLatch(1000);

for(inti = 0; i

< 1000; i++) {

Thread

thread = newThread() {

@Override

publicvoidrun()

{

ai.incrementAndGet();

System.out.println("-------"+

ai.get());

latch.countDown();

}

};

thread.setDaemon(true);

thread.start();

}

Thread

thread = newThread() {

@Override

publicvoidrun()

{

while(true)

{

ai.incrementAndGet();

System.out.println("---循環----"+ ai.get());

}

//

latch.countDown();

}

};

//

thread.setDaemon(true);

thread.start();

latch.await();

// while

(true) {

System.out.println("ai : "

+ ai.get());

//

Thread.sleep(100);

//

}

}

}

latch.await(); 使目前線程在鎖存器倒計數至零之前一直等待,除非線程被中斷。用來保證for循環執行結束以後列印結果。

AtomicInteger操作是原子性的

二:volatile

publicclassCounter

{

publicstaticintcount=

0;

publicstaticvoidinc()

{

// 這裡延遲1毫秒,使得結果明顯

try{

Thread.sleep(1);

}

catch(InterruptedException e) {

}

count++;

}

publicstaticvoidmain(String[]

args) throwsInterruptedException {

// 同時啟動1000個線程,去進行i++計算,看看實際結果

finalCountDownLatch

latch = newCountDownLatch(1000);

for(inti = 0; i

< 1000; i++) {

newThread(newRunnable()

{

@Override

publicvoidrun()

{

latch.countDown();

try{

latch.await();

}

catch(InterruptedException e) {

//

TODOAuto-generated catch block

e.printStackTrace();

}

Counter.inc();

}

}).start();

}

// 這裡每次運作的值都有可能不同,可能為1000

while(true)

{

System.out.println("運作結果:Counter.count="+

Counter.count);

Thread.sleep(100);

}

}

}

運作結果:Counter.count=992

運作結果還是沒有我們期望的1000,下面我們分析一下原因

在 java

垃圾回收整理一文中,描述了jvm運作時刻記憶體的配置設定。其中有一個記憶體區域是jvm虛拟機棧,每一個線程運作時都有一個線程棧,

線程棧儲存了線程運作時候變量值資訊。當線程通路某一個對象時候值的時候,首先通過對象的引用找到對應在堆記憶體的變量的值,然後把堆記憶體

變量的具體值load到線程本地記憶體中,建立一個變量副本,之後線程就不再和對象在堆記憶體變量值有任何關系,而是直接修改副本變量的值,

在修改完之後的某一個時刻(線程退出之前),自動把線程變量副本的值回寫到對象在堆中變量。這樣在堆中的對象的值就産生變化了。