黑马程序员_Java基础[26]_线程2、同步代码块、同步函数

---------- android培训 java培训 、期待与您交流! ----------

【同步代码块】


 * *在【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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章