Java多线程编程核心技术(第3版)
上QQ阅读APP看书,第一时间看更新

2.2.12 细化验证3个结论

synchronized(非this对象x)表示将x对象本身作为“对象监视器”,这样就可以分析出3个结论。

□当多个线程同时执行synchronized(x){}同步代码块时呈同步效果。

□当其他线程执行x对象中synchronized同步方法时呈同步效果。

□当其他线程执行x对象方法里面的synchronized(this)代码块时也呈现同步效果。

注意

如果其他线程调用不加synchronized关键字的方法时还是异步调用。

为了验证这3个结论,创建实验项目synchronizedBlockLockAll。

先来验证第1个结论:当多个线程同时执行synchronized(x){}同步代码块时呈同步效果。

创建名称为test1的包。类MyObject.java代码如下:


package test1.extobject;

public class MyObject {
}

类Service.java代码如下:


package test1.service;

import test1.extobject.MyObject;

public class Service {

public void testMethod1(MyObject object) {
    synchronized (object) {
        try {
            System.out.println("testMethod1 ____getLock time="
                + System.currentTimeMillis() + " run ThreadName="
                + Thread.currentThread().getName());
            Thread.sleep(2000);
            System.out.println("testMethod1 releaseLock time="
                + System.currentTimeMillis() + " run ThreadName="
                + Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

}

两个自定义线程代码如图2-37所示。

图2-37 线程代码

类文件Run1_1.java代码如下:


package test1.run;

import test1.extobject.MyObject;
import test1.extthread.ThreadA;
import test1.extthread.ThreadB;
import test1.service.Service;

public class Run1_1 {

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

    ThreadA a = new ThreadA(service, object);
    a.setName("a");
    a.start();

    ThreadB b = new ThreadB(service, object);
    b.setName("b");
    b.start();
}

}

程序运行结果如图2-38所示。

图2-38 同步效果

同步的原因是使用同一把锁,如果使用不同的锁会出现什么样的效果呢?

创建类文件Run1_2.java,代码如下:


package test1.run;

import test1.extobject.MyObject;
import test1.extthread.ThreadA;
import test1.extthread.ThreadB;
import test1.service.Service;

public class Run1_2 {

public static void main(String[] args) {
    Service service = new Service();
    MyObject object1 = new MyObject();
    MyObject object2 = new MyObject();

    ThreadA a = new ThreadA(service, object1);
    a.setName("a");
    a.start();

    ThreadB b = new ThreadB(service, object2);
    b.setName("b");
    b.start();
}

}

程序执行结果如图2-39所示。

图2-39 异步调用,因为是不同的锁

继续验证第2个结论:当其他线程执行x对象中的synchronized同步方法时呈同步效果。

创建名称为test2的包。类MyObject.java代码如下:


package test2.extobject;

public class MyObject {
synchronized public void speedPrintString() {
    System.out.println("speedPrintString ____getLock time="
        + System.currentTimeMillis() + " run ThreadName="
        + Thread.currentThread().getName());
    System.out.println("-----------------");
    System.out.println("speedPrintString releaseLock time="
        + System.currentTimeMillis() + " run ThreadName="
        + Thread.currentThread().getName());
}
}

类Service.java代码如下:


package test2.service;

import test2.extobject.MyObject;

public class Service {

public void testMethod1(MyObject object) {
    synchronized (object) {
        try {
            System.out.println("testMethod1 ____getLock time="
                + System.currentTimeMillis() + " run ThreadName="
                + Thread.currentThread().getName());
            Thread.sleep(5000);
            System.out.println("testMethod1 releaseLock time="
                + System.currentTimeMillis() + " run ThreadName="
                + Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

}

两个自定义线程代码如图2-40所示。

类Run.java代码如下:


package test2.run;

import test2.extobject.MyObject;
import test2.extthread.ThreadA;
import test2.extthread.ThreadB;
import test2.service.Service;

public class Run {

public static void main(String[] args) throws InterruptedException {
    Service service = new Service();
    MyObject object = new MyObject();

    ThreadA a = new ThreadA(service, object);
    a.setName("a");
    a.start();

    Thread.sleep(100);

    ThreadB b = new ThreadB(object);
    b.setName("b");
    b.start();
}

}

图2-40 自定义线程代码

程序运行结果如图2-41所示。

图2-41 同步效果

继续验证第3个结论:当其他线程执行x对象方法里面的synchronized(this)代码块时也呈现同步效果。

创建名称为test3的包。创建名称为MyObject.java的类,代码如下:


package test3.extobject;

public class MyObject {
public void speedPrintString() {
    synchronized (this) {
        System.out.println("speedPrintString ____getLock time="
            + System.currentTimeMillis() + " run ThreadName="
            + Thread.currentThread().getName());
        System.out.println("-----------------");
        System.out.println("speedPrintString releaseLock time="
            + System.currentTimeMillis() + " run ThreadName="
            + Thread.currentThread().getName());
    }
}
}

其他代码与test2包中Java类的代码一样,程序运行结果如图2-42所示。

图2-42 同样也是同步效果