Synchronized的使用方法

 

 

 

 


 同步鎖機制:
在《Thinking in Java》中,是這麼說的:對於併發工做,你須要某種方式來防
止兩個任務訪問相同的資源(其實就是共享資源競爭)。 防止這種衝突的方法
就是當資源被一個任務使用時,在其上加鎖。第一個訪問某項資源的任務必須
鎖定這項資源,使其餘任務在其被解鎖以前,就沒法訪問它了,而在其被解鎖
之時,另外一個任務就能夠鎖定並使用它了。
 synchronized 的鎖是什麼 ?
任意對象均可以做爲同步鎖。全部對象都自動含有單一的鎖(監視器)。
同步方法的鎖:靜態方法(類名.class)、非靜態方法(this)
同步代碼塊:本身指定,不少時候也是指定爲this或類名.class
注意:
必須確保使用同一個資源的 多個線程共用一把鎖,這個很是重要,不然就
沒法保證共享資源的安全
一個線程類中的全部靜態方法共用同一把鎖(類名.class),全部非靜態方
法共用同一把鎖(this),同步代碼塊(指定需謹慎)java

 

使用同步代碼塊解決繼承Thread類的方式的線程安全問題
package com.atguigu.java;


/**
 * 使用同步代碼塊解決繼承Thread類的方式的線程安全問題
 *
 * 例子:建立三個窗口賣票,總票數爲100張.使用繼承Thread類的方式
 *
 * 說明:在繼承Thread類建立多線程的方式中,慎用this充當同步監視器,考慮使用當前類充當同步監視器。
 *
 * @author ch
 * @create 2021-02-13 下午 4:20
 */
class Window2 extends Thread{


    private static int ticket = 100;

    private static Object obj = new Object();

    @Override
    public void run() {

        while(true){
            //正確的
//            synchronized (obj){
            synchronized (Window2.class){//Class clazz = Window2.class,Window2.class只會加載一次
                //錯誤的方式:this表明着t1,t2,t3三個對象
//              synchronized (this){

                if(ticket > 0){

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println(getName() + ":賣票,票號爲:" + ticket);
                    ticket--;
                }else{
                    break;
                }
            }

        }

    }
}


public class WindowTest2 {
    public static void main(String[] args) {
        Window2 t1 = new Window2();
        Window2 t2 = new Window2();
        Window2 t3 = new Window2();


        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

        t1.start();
        t2.start();
        t3.start();

    }
}
使用同步方法解決實現Runnable接口的線程安全問題
 
package com.atguigu.java;

/**
 * 使用同步方法解決實現Runnable接口的線程安全問題
 *
 *
 *  關於同步方法的總結:
 *  1. 同步方法仍然涉及到同步監視器,只是不須要咱們顯式的聲明。
 *  2. 非靜態的同步方法,同步監視器是:this
 *     靜態的同步方法,同步監視器是:當前類自己
 *
 * @author ch
 * @create 2021-02-15 上午 11:35
 */


class Window3 implements Runnable {

    private int ticket = 100;

    @Override
    public void run() {
        while (true) {

            show();
        }
    }

    private synchronized void show(){//同步監視器:this
        //synchronized (this){

            if (ticket > 0) {

                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println(Thread.currentThread().getName() + ":賣票,票號爲:" + ticket);

                ticket--;
            }
        //}
    }
}


public class WindowTest3 {
    public static void main(String[] args) {
        Window3 w = new Window3();

        Thread t1 = new Thread(w);
        Thread t2 = new Thread(w);
        Thread t3 = new Thread(w);

        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

        t1.start();
        t2.start();
        t3.start();
    }

}
 
使用同步方法處理繼承Thread類的方式中的線程安全問題
 
package com.atguigu.java;

/**
 * 使用同步方法處理繼承Thread類的方式中的線程安全問題
 *
 * @author ch
 * @create 2021-02-15 上午 11:43
 */
class Window4 extends Thread {


    private static int ticket = 100;

    @Override
    public void run() {

        while (true) {

            show();
        }

    }
    private static synchronized void show(){//同步監視器:Window4.class
        //private synchronized void show(){ //同步監視器:t1,t2,t3。此種解決方式是錯誤的
        if (ticket > 0) {

            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread().getName() + ":賣票,票號爲:" + ticket);
            ticket--;
        }
    }
}


public class WindowTest4 {
    public static void main(String[] args) {
        Window4 t1 = new Window4();
        Window4 t2 = new Window4();
        Window4 t3 = new Window4();


        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

        t1.start();
        t2.start();
        t3.start();

    }
}
 

 

相關文章
相關標籤/搜索