1. 程式人生 > >synchronized驗證3個理論(菜鳥玩執行緒)

synchronized驗證3個理論(菜鳥玩執行緒)

synchronized驗證3個理論

1.論證1

1.1理論

當多個執行緒同時執行synchronized(非this)同步程式碼塊時呈同步效果。

1.2落地

1.2.1自定義鎖物件類

package com.chapter02.thread2_2_8_1;
public class MyObject {
}

1.2.2自定義共享變數類

package com.chapter02.thread2_2_8_1;

public class Service {
    public void testMethod1(MyObject myObject) {
        synchronized (
myObject) { try { System.out.println("testMethod1 , GET LOCK TIME = " + System.currentTimeMillis() + " , RUN THREAD NAME = " + Thread.currentThread().getName()); Thread.sleep(2000); System.out.println("testMethod1 , RELEASE LOCK TIME = " + System.
currentTimeMillis() + " , RUN THREAD NAME = " + Thread.currentThread().getName()); } catch (Exception ex) { ex.printStackTrace(); } } } }

1.2.3自定義執行緒1

package com.chapter02.thread2_2_8_1;


public class MyThread1 extends Thread {
    private Service service;
private MyObject myObject; public MyThread1(Service service, MyObject myObject) { this.service = service; this.myObject = myObject; } @Override public void run() { service.testMethod1(myObject); } }

1.2.4自定義執行緒2

package com.chapter02.thread2_2_8_1;

public class MyThread2 extends Thread {
    private Service service;
    private MyObject myObject;

    public MyThread2(Service service, MyObject myObject) {
        this.service = service;
        this.myObject = myObject;
    }

    @Override
    public void run() {
        service.testMethod1(myObject);
    }
}

1.2.5啟動類

package com.chapter02.thread2_2_8_1;

public class Run {
    public static void main(String[] args) {
        Service service = new Service();
        MyObject myObject = new MyObject();

        MyThread1 myThread1 = new MyThread1(service, myObject);
        myThread1.setName("A");
        myThread1.start();

        MyThread2 myThread2 = new MyThread2(service, myObject);
        myThread2.setName("B");
        myThread2.start();
    }
}

1.2.6執行結果

testMethod1 , GET LOCK TIME = 1541647565104 , RUN THREAD NAME = A
testMethod1 , RELEASE LOCK TIME = 1541647567105 , RUN THREAD NAME = A
testMethod1 , GET LOCK TIME = 1541647567105 , RUN THREAD NAME = B
testMethod1 , RELEASE LOCK TIME = 1541647569106 , RUN THREAD NAME = B

如上,同步輸出。

1.3補充

如果使用不同的物件監控器會出現什麼效果呢?

1.3.1修改啟動類

package com.chapter02.thread2_2_8_1;

public class Run {
    public static void main(String[] args) {
        Service service = new Service();
        MyObject myObject1 = new MyObject();

        MyThread1 myThread1 = new MyThread1(service, myObject1);
        myThread1.setName("A");
        myThread1.start();

        MyObject myObject2 = new MyObject();
        MyThread2 myThread2 = new MyThread2(service, myObject2);
        myThread2.setName("B");
        myThread2.start();
    }
}

1.3.2執行結果

testMethod1 , GET LOCK TIME = 1541648070884 , RUN THREAD NAME = A
testMethod1 , GET LOCK TIME = 1541648070885 , RUN THREAD NAME = B
testMethod1 , RELEASE LOCK TIME = 1541648072885 , RUN THREAD NAME = A
testMethod1 , RELEASE LOCK TIME = 1541648072885 , RUN THREAD NAME = B

不同步輸出!!!

2.論證2

2.1理論

當其他執行緒執行X物件中的synchronized同步方法時呈現同步效果

2.2落地

2.2.1自定義鎖物件類

package com.chapter02.thread2_2_8_2;
public class MyObject {
    synchronized public void speedPrintString() {
        System.out.println("speedPrintString , GET LOCK TIME = " + System.currentTimeMillis() + " , RUN THREAD NAME = " + Thread.currentThread().getName());
        System.out.println("***********************************");
        System.out.println("speedPrintString , RELEASE LOCK TIME = " + System.currentTimeMillis() + " , RUN THREAD NAME = " + Thread.currentThread().getName());
    }
}

2.2.2自定義共享變數類

package com.chapter02.thread2_2_8_2;
public class Service {
    public void testMethod1(MyObject myObject) {
        synchronized (myObject) {
            try {
                System.out.println("testMethod1 , GET LOCK TIME = " + System.currentTimeMillis() + " , RUN THREAD NAME = " + Thread.currentThread().getName());
                Thread.sleep(5000);
                System.out.println("testMethod1 , RELEASE LOCK TIME = " + System.currentTimeMillis() + " , RUN THREAD NAME = " + Thread.currentThread().getName());
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }
}

2.2.3自定義執行緒1

package com.chapter02.thread2_2_8_2;
public class MyThread1 extends Thread {
    private Service service;
    private MyObject myObject;

    public MyThread1(Service service, MyObject myObject) {
        this.service = service;
        this.myObject = myObject;
    }

    @Override
    public void run() {
        service.testMethod1(myObject);
    }
}

2.2.4自定義執行緒2

package com.chapter02.thread2_2_8_2;
public class MyThread2 extends Thread {
    private MyObject myObject;

    public MyThread2(MyObject myObject) {
        this.myObject = myObject;
    }

    @Override
    public void run() {
        myObject.speedPrintString();
    }
}

2.2.5啟動類

package com.chapter02.thread2_2_8_2;

public class Run {
    public static void main(String[] args) {
        Service service = new Service();
        MyObject myObject = new MyObject();

        MyThread1 myThread1 = new MyThread1(service, myObject);
        myThread1.setName("A");
        myThread1.start();

        //注:與執行緒1握的同一把鎖,執行不同的方法
        MyThread2 myThread2 = new MyThread2(myObject);
        myThread2.setName("B");
        myThread2.start();
    }
}

2.2.6執行結果

testMethod1 , GET LOCK TIME = 1541648591356 , RUN THREAD NAME = A
testMethod1 , RELEASE LOCK TIME = 1541648596356 , RUN THREAD NAME = A
speedPrintString , GET LOCK TIME = 1541648596357 , RUN THREAD NAME = B
***********************************
speedPrintString , RELEASE LOCK TIME = 1541648596357 , RUN THREAD NAME = B

如上,同步輸出。

3.論證3

3.1理論

當其他執行緒執行X物件方法裡面的synchronized(this)程式碼塊時也呈現同步效果。

3.2落地

3.2.1在論證2的基礎上修改自定義鎖物件類MyObject

package com.chapter02.thread2_2_8_2;
public class MyObject {
    public void speedPrintString() {
        synchronized(this){
            System.out.println("speedPrintString , GET LOCK TIME = " + System.currentTimeMillis() + " , RUN THREAD NAME = " + Thread.currentThread().getName());
        System.out.println("***********************************");
        System.out.println("speedPrintString , RELEASE LOCK TIME = " + System.currentTimeMillis() + " , RUN THREAD NAME = " + Thread.currentThread().getName());
        }
    }
}

3.2.2執行結果

testMethod1 , GET LOCK TIME = 1541649000658 , RUN THREAD NAME = A
testMethod1 , RELEASE LOCK TIME = 1541649005658 , RUN THREAD NAME = A
speedPrintString , GET LOCK TIME = 1541649005659 , RUN THREAD NAME = B
***********************************
speedPrintString , RELEASE LOCK TIME = 1541649005659 , RUN THREAD NAME = B