synchronized驗證3個理論(菜鳥玩執行緒)
阿新 • • 發佈:2019-02-18
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