16、静态同步synchronized方法与synchronized(class)代码块

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

静态同步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)与同步静态方法的作用一样。

猜你喜欢

转载自blog.csdn.net/toyota_rav4/article/details/85012800