1.Static并不能保證在各個(gè)線程中值的一致策添,因?yàn)槊總€(gè)線程有自己的工作內(nèi)存材部,工作內(nèi)存中的變量值是主內(nèi)存中的拷貝,沒有重新從主內(nèi)存中加載時(shí)唯竹,并不能知道別的線程對(duì)這個(gè)變量做了什么修改乐导。
public static boolean isRun = true;
public static void main(String[] args) throws InterruptedException {
Thread1 t1 = new Thread1(1);
t1.start();
Thread.sleep(1000);
isRun = false;
System.err.println("--------stop");;
}
static class Thread1 extends Thread{
private int flag;
public Thread1(int flag) {
this.flag = flag;
}
@Override
public void run() {
super.run();
while(true) {
if(!isRun) {
System.err.println(flag+"," + isRun);
break;
}
}
}
}
結(jié)果如下
--------stop
結(jié)果是stop已經(jīng)打印出來,線程中的循環(huán)結(jié)束不了浸颓,因?yàn)榫€程的工作內(nèi)存中的isRun值還是true物臂,并沒有重新從主內(nèi)存中獲取修改后的值。
2.Volatile猾愿,java內(nèi)存模型保證volatile修飾的變量在各個(gè)線程中保持一致鹦聪,即可見性保證。當(dāng)一個(gè)線程修改了該變量的值蒂秘,修改后的值可以立即被其他線程獲取到泽本。
(ps:普通變量的值如果要在線程間傳遞要通過主內(nèi)存做過渡,及A線程要把修改后的值同步回主內(nèi)存姻僧,B線程要從主內(nèi)存中獲取才能獲得普通變量的新值规丽。)
(ps: Volatile保證可見性蒲牧,并不能保證對(duì)volatile的所有操作都是線程安全,這還要考慮操作的原子性赌莺,如volatile int i; i++;并不是原子操作,靠volatile不能保證其線程安全冰抢。)
將上面例子中的isRun加上volatile修飾。
public static volatile boolean isRun = true;
// public static boolean isRun = true;
public static void main(String[] args) throws InterruptedException {
Thread1 t1 = new Thread1(1);
t1.start();
Thread.sleep(1000);
isRun = false;
System.err.println("--------stop");;
}
static class Thread1 extends Thread{
private int flag;
public Thread1(int flag) {
this.flag = flag;
}
@Override
public void run() {
super.run();
while(true) {
if(!isRun) {
System.err.println(flag+"," + isRun);
break;
}
}
}
}
結(jié)果如下
--------stop
1,false
3.Synchronized 在保證互斥的同時(shí)艘狭,還可以保證可見挎扰。在進(jìn)入同步代碼塊時(shí)會(huì)使當(dāng)前線程的工作內(nèi)存失效,強(qiáng)制從主內(nèi)存重新獲取巢音。
所以如第一個(gè)例子在線程中加上synchronized代碼塊時(shí)
public static boolean isRun = true;
public static void main(String[] args) throws InterruptedException {
Thread1 t1 = new Thread1(1);
t1.start();
Thread.sleep(1000);
isRun = false;
System.err.println("--------stop");;
}
static class Thread1 extends Thread{
private int flag;
public Thread1(int flag) {
this.flag = flag;
}
@Override
public void run() {
super.run();
while(true) {
if(!isRun) {
System.err.println(flag+"," + isRun);
break;
}
//System.err.println("thread is running.");
synchronized ("") {
}
}
}
}
結(jié)果如下
--------stop
1,false
另外一點(diǎn)在測(cè)試中發(fā)現(xiàn)的是遵倦,其實(shí)在線程中System.....print和加同步代碼塊是一樣的效果」俸常看System....print的源碼梧躺,其實(shí)就是synchronized。
public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
}