/*
* 解決線程併發問題
*/
package com.test.thread;
public class Test1 {
public static void main(String []args){
//創建一個售票窗口
TicketWindow tw1 = new TicketWindow();
Thread t1 = new Thread(tw1);
Thread t2 = new Thread(tw1);
Thread t3 = new Thread(tw1);
//三個線程啓動售票
t1.start();
t2.start();
t3.start();
}
}
class TicketWindow implements Runnable{
private int tickets = 1000;
@Override
public void run() {
// TODO 自動生成的方法存根
while(true){
//同步代碼塊
//synchronized(this){
if(tickets>0){
System.out.println(Thread.currentThread().getName()+"賣出第"+tickets+"張票");
tickets--;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO 自動生成的 catch 塊
e.printStackTrace();
}
}else{
break;
}
// }//同步代碼塊
}
}
}
若註釋掉sychronized(Object)語句的,執行結果如下:
Thread-0賣出第1000張票
Thread-2賣出第999張票
Thread-1賣出第998張票
Thread-0賣出第997張票
Thread-1賣出第996張票
Thread-2賣出第996張票
Thread-0賣出第994張票
Thread-2賣出第993張票
Thread-1賣出第993張票
Thread-0賣出第991張票
多線程併發,給我們的編程帶來很多,提高程序效率,同時也會帶來線程安全的問題。如以上情況,在出現線程併發時,會導致出現多次售出同一張票的情況,去掉sychronized(Object)語句的註釋則不會出現以上情況。
對同步機制的解釋
java任意類型的對象都有一個標誌位(用術語來講,可以稱爲對象鎖),該標誌位具有0,1兩種狀態,其開始狀態爲1,當某個純種執行到了sychronized(Object)語句後,objec對象的標誌爲變爲0的狀態,直到執行完整個sychronized語句中的代碼塊後,該對象的標誌位又回到1狀態。
當一個線程執行到sychronized(Object)語句的時候,先檢查object對象的標誌位,如果爲0狀態,表明已經有另外的純種正在執行sychronized代碼塊內中的代碼,那麼這個線程將暫時阻塞,讓出cpu資源,直到另外的線程執行完相關的同步代碼,並將object對象的標誌位變爲1狀態, 這個線程的阻塞就會被取消,線程能繼續運行,該線程又會將object的標誌爲變0狀態,防止其他線程再進入相關的同步代碼塊中。