【同步代碼塊】
* *在【a】手動添加休眠10毫秒,
*通過分析發現 打印出了0 -1 -2 等錯票
*多線程的運行出現了安全無問題。
*問題的原因:
* 當多條語句在操作同一個線程共享數據時,一個線程對多個語句只執行流量一部分,
* 還沒有執行完,另一個線程參與進來執行,導致共享數據的錯誤
*
*解決辦法就是,
* 對多條操作共享數據的語句,只能讓一個線程都執行完,在執行過程中,其他現在不可以參與執行
*
*java對多線程的安全問題,提供了專業的解決方式
*
*就是【同步代碼塊】:
*
*sychronized(對象){
* 需要被同步的代碼
*}
*
*對象如同鎖,持有鎖的線程可以在同步中執行。
*沒有持有鎖的線程即使獲取到cpu的執行權,也進不去,因爲沒有獲取鎖。
*
*火車上的衛生間- - 經典解釋鎖的例子。
*
*
*同步的【前提】:
*1、必須要有2個或者2個以上的線程
*2、必須是多個線程使用同一個鎖
*
*必須保證同步中只能一個線程在運行
*
*【好處】:解決了多線程的安全問題
*
*【弊端】:多個線程都需要判斷鎖,較爲消耗資源。
*/
class Ticket1 implements Runnable{//方式二
private int tick=100;
Object obj=new Object();
public void run(){
while(true){
synchronized(obj){//obj 就相當於鎖。
if(tick>0){
try{
Thread.sleep(10);//【a】
}
catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"買票"+(tick--));
}
}
}
}
}
public class D_Th_test3 {
public static void main(String[] args) {
Ticket t=new Ticket();//這只是創建對象
Thread t1=new Thread(t);
Thread t2=new Thread(t);
Thread t3=new Thread(t);
t1.start();
t2.start();
t3.start();
/*把Runnable 子類對象當作參數傳遞給Thread方法的構造函數,
* 通過調用Thread類的start方法開啓線程並調用Runnable中的run方法
*/
}
}
-----------------------------------------------------------------------------------------------------------
/*sychronized 練習
* 需求:
* 銀行有一個金庫
* 有兩個儲戶,分別存300,每次100 存3次。
*
* 目的:該程序是否有安全問題,如果有,如何解決。】
*
* 如何找到問題
* 1、明確那些代碼是多線程代碼
* 2、明確共享數據
* 3、明確多線程中那些語句是操作共享數據的
*
* 【同步有2種表現形式】:
* 1、同步代碼塊 synchronized(對象){}
* 2、同步函數[b]
*
* 下列:【test2】
* 返回去看剛剛test2賣票的小案例,他能使用同步函數嗎,
* 答案是否定的,因爲while是不需要同步的,鎖到一起後,會出現一直循環打印的現象。
* 我們知道 synchronized中的鎖是對象的,下來中的對象是誰?我們知道,show()前面減省了this,應該是 this.show();
* 那麼這個鎖就是this的。【明天繼續,實在是困了。】
*
* 同步函數,到底用的是那一個鎖
* 【非靜態同步函數用的鎖,是this】
*
* 通過該程序來賣票
* 使用兩個線程來賣票
* 一個線程在同步代碼塊中,
* 一個線程在同步函數中,
* 都在執行賣票動作。
*
* 下列代碼運行觀察,有一定機率打印出0號票,
* 我們把run方法中傳入的obj鎖改爲this,我們在試試
* 更改後,多次運行均無0出現
*
* 所以,推理得出同步函數使用的鎖是this
*
*
*
*/
//[b] 同步函數
class Ticket4 implements Runnable{//方式二
private int tick=100;
Object obj=new Object();
boolean flag=true;
public void run(){
if(flag){
while(true){
//synchronized(obj){//obj 就相當於鎖。
synchronized(this){//更換爲this
if(tick>0){
try{
Thread.sleep(10);//【a】
}
catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"買票"+(tick--));
}
}
}
}
else{
while(true)
show();
}
}
public synchronized void show(){
if(tick>0){
try{
Thread.sleep(10);//【a】
}
catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"買票"+(tick--));
}
}
}
public class D_Th_test5 {
public static void main(String[] args) {
Ticket4 t=new Ticket4();
Thread t1=new Thread(t);
Thread t2=new Thread(t);
t1.start();
try{
Thread.sleep(10);//【a】
}
catch(Exception e){}
t.flag=false;
t2.start();
}
}
---------- android培訓、 java培訓 、期待與您交流!----------
黑馬官網: http://edu.csdn.net/heima