15、将任意对象作为对象监视器

版权声明:版权归 爱装逼的文艺小青年所有 https://blog.csdn.net/toyota_rav4/article/details/85010000

在前面的博文中,我们提到了synchronized同步方法和使用synchronized(this),通过前面的实验可以发现:多个线程调用同一个对象中不同名称的synchronized同步方法或者sychronized(this)代码块,调用的效果是按顺序执行的,也就是说是阻塞的!

本篇博文我们将写到的是关于java中可以将任意对象作为对象监视器

当多个线程持有的“对象监视器”为同一个对象的前提下,同一时间只有一个线程可以执行synchronized(非this对象)同步代码块中的代码!

package com.demo17;

public class MyObject {
    private String username;
    private String password;
    private String obj = new String();
    public void setValue(String username , String password){
        try {
            synchronized (obj) {
                System.out.println("进入赋值方法的线程名称:" + Thread.currentThread().getName() +
                    "时间:" + System.currentTimeMillis());
                this.username = username;
                Thread.sleep(2000);
                this.password = password;
                System.out.println("离开赋值方法的线程名称:" + Thread.currentThread().getName() +
                        " 时间:" + System.currentTimeMillis() +
                        " username = " + username +
                        " password = " + password);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
package com.demo17;

public class ThreadA extends Thread {
    private MyObject myObject;

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

    @Override
    public void run(){
        myObject.setValue("a","aa");
    }
}
package com.demo17;

public class ThreadB extends Thread {
    private MyObject myObject;

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

    @Override
    public void run() {
        myObject.setValue("b","bb");
    }
}
package com.demo17;

public class Run {
    public static void main(String[] args) {
        MyObject myObject = new MyObject();
        ThreadA threadA = new ThreadA(myObject);
        ThreadB threadB = new ThreadB(myObject);
        threadA.setName("A");
        threadB.setName("B");
        threadA.start();
        threadB.start();
    }
}

运行结果:

进入赋值方法的线程名称:A时间:1544795048292
离开赋值方法的线程名称:A 时间:1544795050293 username = a password = aa
进入赋值方法的线程名称:B时间:1544795050293
离开赋值方法的线程名称:B 时间:1544795052294 username = b password = bb

很明显是阻塞的,同步执行的!

修改MyObject如下:让多个线程持有的“对象监视器”不为同一个对象

package com.demo17;

public class MyObject {
    private String username;
    private String password;
    //private String obj = new String();
    public void setValue(String username , String password){
        try {
            String obj = new String();
            synchronized (obj) {
                System.out.println("进入赋值方法的线程名称:" + Thread.currentThread().getName() +
                    "时间:" + System.currentTimeMillis());
                this.username = username;
                Thread.sleep(2000);
                this.password = password;
                System.out.println("离开赋值方法的线程名称:" + Thread.currentThread().getName() +
                        " 时间:" + System.currentTimeMillis() +
                        " username = " + username +
                        " password = " + password);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行结果:

进入赋值方法的线程名称:A时间:1544796228604
进入赋值方法的线程名称:B时间:1544796228604
离开赋值方法的线程名称:A 时间:1544796230607 username = a password = aa
离开赋值方法的线程名称:B 时间:1544796230608 username = b password = bb

如果不是同一个对象监视器,运行的结果是异步的!

为了验证上述结论,我们再继续进行实验:

package com.demo18;

public class MyObject {
    private String obj = new String ();
    public void a(){
        try {
            synchronized (obj) {
                System.out.println("a begin");
                Thread.sleep(2000);
                System.out.println("a end");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    synchronized public void b(){
        System.out.println("b begin");
        System.out.println("b end");
    }
}
package com.demo18;

public class ThreadA extends Thread {
    private MyObject myObject;

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

    @Override
    public void run() {
        myObject.a();
    }
}
package com.demo18;

public class ThreadB extends Thread{
    private MyObject myObject;

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

    @Override
    public void run() {
        myObject.b();
    }
}
package com.demo18;

public class Run {
    public static void main(String[] args) {
        MyObject myObject = new MyObject();
        ThreadA threadA = new ThreadA(myObject);
        ThreadB threadB = new ThreadB(myObject);
        threadA.start();
        threadB.start();
    }
}

运行结果:

a begin
b begin
b end
a end

synchronized(非this对象)代码块与 synchronized 同步方法是异步执行的效果。

修改MyOBject如下,将同步方法换成sychronized(this)同步代码块

package com.demo18;

public class MyObject {
    private String obj = new String ();
    public void a(){
        try {
            synchronized (obj) {
                System.out.println("a begin");
                Thread.sleep(2000);
                System.out.println("a end");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
     public void b(){
        synchronized (this) {
            System.out.println("b begin");
            System.out.println("b end");
        }
    }
}

运行结果:

a begin
b begin
b end
a end

结论:synchronized(非this对象)代码块与synchronized(this)代码块是异步执行的效果。

猜你喜欢

转载自blog.csdn.net/toyota_rav4/article/details/85010000
今日推荐