線程安全概念:當(dāng)多個線程訪問某個類(對象或方法)時抬旺,這個類始終都能表現(xiàn)出正確的行為,那么這個類就是線程安全的。
synchronized:可以在任意對象及方法上加鎖,而加鎖的這段代碼稱為“互斥區(qū)” 或“臨界區(qū)”
示例:
public class MyThread extends Thread {
private int count = 5 ;
@Override
public void run() {
count -- ;
System.out.println(this.currentThread().getName() + ": count is " + count);
}
public static void main(String[] args) {
MyThread myThread = new MyThread();
Thread t1 = new Thread(myThread, "t1");
Thread t2 = new Thread(myThread, "t2");
Thread t3 = new Thread(myThread, "t3");
Thread t4 = new Thread(myThread, "t4");
Thread t5 = new Thread(myThread, "t5");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}}
如上代碼诫尽,方法上我們并沒有加鎖。同時運(yùn)行5個線程炬守,期望count能夠按照我們預(yù)期的依次遞減牧嫉。但是結(jié)果如下
其中并沒有按照我們預(yù)期中的進(jìn)行遞減,這是因為當(dāng)多個線程訪問MyThread的run方法時减途,是以CPU分配的先后順序進(jìn)行的酣藻,并不是按照代碼的先后順序。所以很有可能當(dāng)某段代碼還沒執(zhí)行完鳍置,CPU就把這個資源分配給其他線程了辽剧,導(dǎo)致共享變量的錯亂。
因此税产,做出如下修改:
public class MyThread extends Thread {
private int count = 5 ;
@Override
public synchronized void run() {
count -- ;
System.out.println(this.currentThread().getName() + ": count is " + count);
}
public static void main(String[] args) {
MyThread myThread = new MyThread();
Thread t1 = new Thread(myThread, "t1");
Thread t2 = new Thread(myThread, "t2");
Thread t3 = new Thread(myThread, "t3");
Thread t4 = new Thread(myThread, "t4");
Thread t5 = new Thread(myThread, "t5");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}}
在run方法上加上synchronize怕轿,使其成為一段互斥的代碼。當(dāng)線程嘗試執(zhí)行synchronize修的代碼時辟拷,會先去嘗試獲取鎖撤卢,拿到鎖則執(zhí)行代碼。拿不到則會不斷的嘗試獲取這把鎖梧兼,直到拿到為止,而且是多個線程同時去競爭這把鎖(比如1000個線程智听,只有一個線程能拿到鎖羽杰,其他999個線程去競爭,對我們CPU的壓力就比較大了到推,應(yīng)該盡量避免)