本篇是為了同步問題的引出舞竿。
實(shí)際上所謂的同步指的就是多個線程訪問同一資源所引出的問題物遇。
范例:觀察非同步情況下的操作(多人賣票問題)
package TestDemo;
class MyThread implements Runnable{//Runnable接口子類,也是線程公有對象您炉,其實(shí)例化對象在堆中
private int ticket=5;
@Override
public void run() {
for (int i = 0; i < 20; i++) {
if(this.ticket>0)
System.out.println(Thread.currentThread().getName()+",sell ticket="+this.ticket--);
}
}
}
public class TestDemo{
public static void main(String[] args)throws Exception{
MyThread mt=new MyThread();
new Thread(mt,"seller A").start();
new Thread(mt,"seller B").start();
new Thread(mt,"seller C").start();
new Thread(mt,"seller D").start();
}
}
此時沒有問題出現(xiàn)是因?yàn)樵谝粋€JVM進(jìn)程下運(yùn)行,并且沒有受到任何影響,如果要想觀察到問題农猬,可以加入一個延遲。
package TestDemo;
class MyThread implements Runnable{//Runnable接口子類售淡,也是線程公有對象斤葱,其實(shí)例化對象在堆中
private int ticket=5;
@Override
public void run() {
for (int i = 0; i < 20; i++) {
if(this.ticket>0){
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+",sell ticket="+this.ticket--);
}
}
}
}
public class TestDemo{
public static void main(String[] args)throws Exception{
MyThread mt=new MyThread();
new Thread(mt,"seller A").start();
new Thread(mt,"seller B").start();
new Thread(mt,"seller C").start();
new Thread(mt,"seller D").start();
}
}
發(fā)現(xiàn)出現(xiàn)了臟數(shù)據(jù)准谚。
不僅出現(xiàn)了重復(fù)數(shù)據(jù)弹惦,還出現(xiàn)了負(fù)數(shù),這就是不同步的狀況欠拾,整個賣票的步驟分為兩步:
第一步:判斷是否還有剩余的票數(shù)
第二步:減少剩余票數(shù)
我們可以將中間的休眠想象成高并發(fā)下的程序運(yùn)行汤纸,壓力增大情況下衩茸,如果不對票數(shù)進(jìn)行同步加鎖,就會出現(xiàn)臟數(shù)據(jù)贮泞,設(shè)想一下楞慈,12306搶票的時候,高并發(fā)情況下啃擦,票數(shù)需要加鎖囊蓝,否則就會出現(xiàn)票數(shù)為負(fù)的情況,或者同一張票賣給了兩人议惰,是災(zāi)難性的慎颗。因而線程安全的核心思想:"要么只讀,要么加鎖。"