16、靜態同步synchronized方法與synchronized(class)程式碼塊
阿新 • • 發佈:2018-12-22
靜態同步synchronized方法
package com.demo19; public class MyObject { synchronized public static void a(){ try { System.out.println("執行緒:" + Thread.currentThread().getName() + " 開始時間:" + System.currentTimeMillis()); Thread.sleep(3000); System.out.println("執行緒:" + Thread.currentThread().getName() + " 結束時間:" + System.currentTimeMillis()); } catch (InterruptedException e) { e.printStackTrace(); } } synchronized public static void b(){ System.out.println("執行緒:" + Thread.currentThread().getName() + " 開始時間:" + System.currentTimeMillis()); System.out.println("執行緒:" + Thread.currentThread().getName() + " 結束時間:" + System.currentTimeMillis()); } }
package com.demo19;
public class ThreadA extends Thread {
@Override
public void run() {
MyObject.a();
}
}
package com.demo19;
public class ThreadB extends Thread {
@Override
public void run() {
MyObject.b();
}
}
package com.demo19; public class run { public static void main(String[] args) { ThreadA threadA = new ThreadA(); ThreadB threadB = new ThreadB(); threadA.setName("A"); threadB.setName("B"); threadA.start(); threadB.start(); } }
執行結果:
執行緒:A 開始時間:1544844475598
執行緒:A 結束時間:1544844478598
執行緒:B 開始時間:1544844478598
執行緒:B 結束時間:1544844478598
看上去跟之前使用synchronized同步非靜態方法的效果沒什麼區別,但本質上卻是有區別的。synchronized同步靜態方法,加在class上;synchronized同步非靜態方法,是給物件上鎖。
為了驗證不是同一個鎖,繼續進行實驗。
package com.demo19; public class MyObject { synchronized public static void a(){ try { System.out.println("執行緒:" + Thread.currentThread().getName() + " 開始時間:" + System.currentTimeMillis()); Thread.sleep(3000); System.out.println("執行緒:" + Thread.currentThread().getName() + " 結束時間:" + System.currentTimeMillis()); } catch (InterruptedException e) { e.printStackTrace(); } } synchronized public static void b(){ System.out.println("執行緒:" + Thread.currentThread().getName() + " 開始時間:" + System.currentTimeMillis()); System.out.println("執行緒:" + Thread.currentThread().getName() + " 結束時間:" + System.currentTimeMillis()); } synchronized public void c(){ System.out.println("執行緒:" + Thread.currentThread().getName() + " 開始時間:" + System.currentTimeMillis()); System.out.println("執行緒:" + Thread.currentThread().getName() + " 結束時間:" + System.currentTimeMillis()); } }
package com.demo19;
public class ThreadA extends Thread {
private MyObject myObject;
public ThreadA(MyObject myObject) {
this.myObject = myObject;
}
@Override
public void run() {
MyObject.a();
}
}
package com.demo19;
public class ThreadB extends Thread {
private MyObject myObject;
public ThreadB(MyObject myObject) {
this.myObject = myObject;
}
@Override
public void run() {
MyObject.b();
}
}
package com.demo19;
public class ThreadC extends Thread {
private MyObject myObject;
public ThreadC(MyObject myObject) {
this.myObject = myObject;
}
@Override
public void run(){
myObject.c();
}
}
package com.demo19;
public class run {
public static void main(String[] args) {
MyObject myObject = new MyObject();
ThreadA threadA = new ThreadA(myObject);
ThreadB threadB = new ThreadB(myObject);
ThreadC threadC = new ThreadC(myObject);
threadA.setName("A");
threadB.setName("B");
threadC.setName("C");
threadA.start();
threadB.start();
threadC.start();
}
}
執行結果:
執行緒:A 開始時間:1544845870678
執行緒:C 開始時間:1544845870679
執行緒:C 結束時間:1544845870679
執行緒:A 結束時間:1544845873678
執行緒:B 開始時間:1544845873678
執行緒:B 結束時間:1544845873678
很明顯 非同步,原因是持有不同的鎖。一個是物件鎖,一個是class鎖。class鎖可以對類的所有例項物件起作用!
下面對該結論進行實驗:
package com.demo19;
public class MyObject {
synchronized public static void a(){
try {
System.out.println("執行緒:" + Thread.currentThread().getName() + " 開始時間:" + System.currentTimeMillis());
Thread.sleep(3000);
System.out.println("執行緒:" + Thread.currentThread().getName() + " 結束時間:" + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized public static void b(){
System.out.println("執行緒:" + Thread.currentThread().getName() + " 開始時間:" + System.currentTimeMillis());
System.out.println("執行緒:" + Thread.currentThread().getName() + " 結束時間:" + System.currentTimeMillis());
}
}
package com.demo19;
public class ThreadA extends Thread {
private MyObject myObject;
public ThreadA(MyObject myObject) {
this.myObject = myObject;
}
@Override
public void run() {
MyObject.a();
}
}
package com.demo19;
public class ThreadB extends Thread {
private MyObject myObject;
public ThreadB(MyObject myObject) {
this.myObject = myObject;
}
@Override
public void run() {
MyObject.b();
}
}
package com.demo19;
public class run {
public static void main(String[] args) {
MyObject myObject1 = new MyObject();
MyObject myObject2 = new MyObject();
ThreadA threadA = new ThreadA(myObject1);
ThreadB threadB = new ThreadB(myObject2);
threadA.setName("A");
threadB.setName("B");
threadA.start();
threadB.start();
}
}
執行結果:
執行緒:A 開始時間:1544846287092
執行緒:A 結束時間:1544846290092
執行緒:B 開始時間:1544846290092
執行緒:B 結束時間:1544846290092
通過結論驗證,class鎖可以對類的所有物件例項起作用。
synchronized(class)同步程式碼塊
package com.demo19;
public class MyObject {
public void a(){
synchronized (MyObject.class){
try {
System.out.println("執行緒:" + Thread.currentThread().getName() + " 開始時間:" + System.currentTimeMillis());
Thread.sleep(3000);
System.out.println("執行緒:" + Thread.currentThread().getName() + " 結束時間:" + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void b(){
synchronized(MyObject.class){
System.out.println("執行緒:" + Thread.currentThread().getName() + " 開始時間:" + System.currentTimeMillis());
System.out.println("執行緒:" + Thread.currentThread().getName() + " 結束時間:" + System.currentTimeMillis());
}
}
}
package com.demo19;
public class ThreadA extends Thread {
private MyObject myObject;
public ThreadA(MyObject myObject) {
this.myObject = myObject;
}
@Override
public void run() {
myObject.a();
}
}
package com.demo19;
public class ThreadB extends Thread {
private MyObject myObject;
public ThreadB(MyObject myObject) {
this.myObject = myObject;
}
@Override
public void run() {
myObject.b();
}
}
package com.demo19;
public class run {
public static void main(String[] args) {
MyObject myObject1 = new MyObject();
MyObject myObject2 = new MyObject();
ThreadA threadA = new ThreadA(myObject1);
ThreadB threadB = new ThreadB(myObject2);
threadA.setName("A");
threadB.setName("B");
threadA.start();
threadB.start();
}
}
執行結果:
執行緒:A 開始時間:1544846633091
執行緒:A 結束時間:1544846636092
執行緒:B 開始時間:1544846636092
執行緒:B 結束時間:1544846636092
結論:synchronized(class)與同步靜態方法的作用一樣。