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 對象鎖
}
}
}
// 只要對象不變,即使對象的屬性變化,運行結果還是同步的。