(一)互斥性
互斥性,即原子性。原子,指最小的物質,具體不可再分性。
CPU運算中,對多線程進行時間片分割執行,一個程序塊執行時不可分割,即滿足互斥性原子性。
java中保證互斥性的方法:
1.用sychronized鎖住程序塊,實行互斥
synchronized (lock) {
a++;
}
2.用Atomic對變量操作實行互斥
public final static AtomicInteger TEST_INTEGER = new AtomicInteger(1);
public static void main(String []args) throws InterruptedException {
final Thread []threads = new Thread[20];
for(int i = 0 ; i < 20 ; i++) {
final int num = i;
threads[i] = new Thread() {
public void run() {
int now = TEST_INTEGER.incrementAndGet();
System.out.println("我是線程:" + num + ",我得到值了,增加後的值爲:" + now);
}
};
threads[i].start();
}
for(Thread t : threads) {
t.join();
}
System.out.println("最終運行結果:" + TEST_INTEGER.get());
}
TEST_INTEGER在多線程操作中,最終結果不會出現偏差。JDK的文檔中說:“設計原子類主要用作各種塊,用於實現非阻塞數據結構和相關基礎結構類。compareAndSet()方法不是鎖定的常規替換方法。僅當對象的重要更新限於單個變量時才應用它”。
(二)可見性
cpu和內存速度相差過高,引入緩存(cache、寄存器等);一個線程由線程id、指令計數器PC、寄存器集合和堆棧構成,詳見《程序員的自我修養》。
每個線程有自己的工作內存,修改進程主內存的值,都需要拷貝到工作內存修改後,再回寫,其他線程可能出現,讀取到未回寫的髒數據這種情況。
/**
* 多線程可見性測試
*
* @author peter_wang
* @create-time 2015-1-12 下午3:56:29
*/
public class ThreadVisableDemo {
private static int a = 0;
static class GetNumThread
extends Thread {
@Override
public void run() {
System.out.println(a);//B1
}
}
static class ChangeNumThread
extends Thread {
@Override
public void run() {
a = 1;//A1,A2
}
}
/**
* @param args
*/
public static void main(String[] args) {
GetNumThread getNumThread = new GetNumThread();
ChangeNumThread changeNumThread = new ChangeNumThread();
changeNumThread.start();//C1
getNumThread.start();//C2
}
}
執行結果:輸出0或者1
A1讀取完數據進行操作,寫入到線程A工作內存寫緩存中,不一定實時刷新主內存中a的值,B1可能讀取到舊數據。
java中保證可見性的方法:
1.用sychronized鎖住程序塊,實行互斥
static class GetNumThread
extends Thread {
@Override
public void run() {
synchronized (ThreadVisableDemo.class) {
System.out.println(a);// B1
}
}
}
static class ChangeNumThread
extends Thread {
@Override
public void run() {
synchronized (ThreadVisableDemo.class) {
a = 1;// A1,A2
}
}
}
2.使用volatile,保證變量可見性
private static volatile int a = 0;
3.使用Atomic對變量操作,實現可見性