synchronize同步鎖的應用

1、當存在父子類繼承關係是,子類完全可以通過“可重入鎖”調用父類的同步方法的。

2、同步不能繼承,需要在子類的方法中添加synchronize關鍵字

synchronize同步方法、變量;鎖定當前對象

//  異步調用service1()、service2()、service3()方法時,
//  會等待當前調用的方法完成後才調用下一個方法。
public static class Service {
        synchronized private void service1() {
            System.out.println("service1");
            try {
                Thread.sleep(3000);
                System.out.println("service1 end");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        synchronized private void service2() {
            System.out.println("service2");
        }

        synchronized private void service3() {
            System.out.println("service3");
        }
    }

synchronize(this)同步代碼塊,鎖定當前對象

synchronize(非this對象x)同步代碼塊,鎖定非this對象x

示例代碼:

-----------------重點代碼-----------------------
public static class Service {
        private String anything = "";

        private void service1() {
            synchronized (anything) {
                try {
                    System.out.println("service begin");
                    Thread.sleep(3000);
                    System.out.println("service end");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        synchronized private void service2() {
            System.out.println("service2");
        }
    }
    
-----------------重點代碼-----------------------
    
     public static class MyThread1 extends Thread {
        private final Service service;

        MyThread1(Service service) {
            this.service = service;
        }

        @Override
        public void run() {
            super.run();
            service.service1();
        }
    }

    public static class MyThread2 extends Thread {
        private final Service service;

        MyThread2(Service service) {
            this.service = service;
        }

        @Override
        public void run() {
            super.run();
            service.service2();
        }
    }


    public static void main(String args[]) {
        try {
            Service service = new Service();
            MyThread1 myThread1 = new MyThread1(service);
            myThread1.start();
            MyThread2 myThread2 = new MyThread2(service);
            myThread2.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

打印結果:

service begin
service2
...
service end

分析:

由於對象監視器不同,所以運行結果就是異步的。

同步代碼塊放在非同步synchronize方法中進行聲明,並不能保證調用方法的線程的執行同步/順序性,調用方法是無序的,雖然同步塊中的執行順序是同步的,極易出現“髒讀”問題

Class鎖:對類的所有對象實例起作用。synchronized static private void method()、synchronize(Service.class)

public static class Service {
        public static void method() {
            synchronized (Service.class) {
                System.out.println("Service.class 類鎖");
            }
        }
        synchronized public static void method2(){
            System.out.println("類鎖");
        }
    }

總結:

public static class Service {
        public void method1() {
            synchronized (Service.class) {
                // Service.class 類鎖
            }
        }

        synchronized public static void method2() {
            //  Service.class 類鎖
        }

        public void method3() {
            synchronized (this) {
                // 對象鎖,Service的實例對象
            }
        }

        synchronized public void method4() {
            // 對象鎖,Service的實例對象
        }
    //  一般不使用String作爲對象鎖,因爲常量值相等時是同一個對象
      private final String anything = "";
        public void method5() {
            synchronized (new Object()) {
                // String 對象鎖
            }
        }
}

// 只要對象不變,即使對象的屬性變化,運行結果還是同步的。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章