java多线程之-----静态同步synchronized方法与synchronized(class) 代码块

这个也是我在面试中被问到的一个题目(synchronize修饰静态方法和非静态方法的区别),这个没答出来
关键字synchronized还可以应用在static静态方法上,如果这样写,那是对当前的*.java文件对应的Class类进行持锁,测试项目:类文件Service.java代码如下:

public class Service {
    synchronized public static void PrintA(){
        try {
            System.out.println("线程的名称为:"+Thread.currentThread().getName()+"在"+System.currentTimeMillis()+"进入printA");
            Thread.sleep(3000);
            System.out.println("线程的名称为:"+Thread.currentThread().getName()+"在"+System.currentTimeMillis()+"离开printA");
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
    synchronized public static void PrintB(){

            System.out.println("线程的名称为:"+Thread.currentThread().getName()+"在"+System.currentTimeMillis()+"进入printB");   
            System.out.println("线程的名称为:"+Thread.currentThread().getName()+"在"+System.currentTimeMillis()+"离开printB");

    }
}

ThreadA的代码:


public class ThreadA extends Thread{

    @Override
    public void run() {
        // TODO Auto-generated method stub
        super.run();
        Service.PrintA();
    }


}

ThreadB:

public class ThreadB extends Thread{

    @Override
    public void run() {
        // TODO Auto-generated method stub
        super.run();
        Service.PrintB();
    }


}

运行测试代码:

public class Test1 {
    public static void main(String[] args) throws InterruptedException {    
        ThreadA a = new ThreadA();
        a.setName("A");
        a.start();
        ThreadB b = new ThreadB();
        b.setName("B");
        b.start();

    }
}

运行结果:
这里写图片描述

从运行结果来看,并没有什么特别地方,都是同步的效果,和将synchronized关键字加到非静态static方法上使用的效果是一样的,其实还是有本质上的不同,synchronized关键字加到static静态方法上是给Class类上锁,而synchronized关键字加到非static静态方法上是给对象上锁:

为了验证不是同一个锁。创建新的 项目,Service.java的代码如下:


public class Service {
    synchronized public static void PrintA() {
        try {
            System.out.println("线程的名称为:" + Thread.currentThread().getName()
                    + "在" + System.currentTimeMillis() + "进入printA");
            Thread.sleep(3000);
            System.out.println("线程的名称为:" + Thread.currentThread().getName()
                    + "在" + System.currentTimeMillis() + "离开printA");
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    synchronized public static void PrintB() {
        System.out.println("线程的名称为:" + Thread.currentThread().getName() + "在"
                + System.currentTimeMillis() + "进入printB");

        System.out.println("线程的名称为:" + Thread.currentThread().getName() + "在"
                + System.currentTimeMillis() + "离开printB");
    }

    synchronized public void PrintC() {
        System.out.println("线程的名称为:" + Thread.currentThread().getName() + "在"
                + System.currentTimeMillis() + "进入printB");
        System.out.println("线程的名称为:" + Thread.currentThread().getName() + "在"
                + System.currentTimeMillis() + "离开printB");

    }
}

ThreadA :

public class ThreadA extends Thread{
    private Service service;
    public ThreadA(Service service) {
        // TODO Auto-generated constructor stub
        super();
        this.service = service;
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        super.run();
        service.PrintA();
    }

}

ThreadB:

public class ThreadB extends Thread{
    private Service service;
    public ThreadB(Service service) {
        // TODO Auto-generated constructor stub
        super();
        this.service = service;
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        super.run();
        service.PrintB();
    }

}

ThreadC:

public class ThreadC extends Thread{
    private Service service;
    public ThreadC(Service service) {
        // TODO Auto-generated constructor stub
        super();
        this.service = service;
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        super.run();
        service.PrintC();
    }

}

测试代码类:


public class Test1 {
    public static void main(String[] args) throws InterruptedException {    
        Service service = new Service();
        ThreadA a = new ThreadA(service);
        a.setName("A");
        a.start();
        ThreadB b = new ThreadB(service);
        b.setName("B");
        b.start();
        ThreadC c = new ThreadC(service);
        c.setName("C");
        c.start();

    }
}

运行结果:
这里写图片描述

结果产生异步的原因是持有不同的锁,一个是对象锁,一个是Class锁,而Class锁可以对类的所有对象实例起作用。如果不是Class锁的话,则多个实例就有多个锁,上文章有说到。下面验证Class锁对所有的实例起作用

修改运行测试文件如下:

public class Test1 {
    public static void main(String[] args) throws InterruptedException {    
        Service service = new Service();
        Service service2 = new Service();
        ThreadA a = new ThreadA(service);
        a.setName("A");
        a.start();
        ThreadB b = new ThreadB(service2);
        b.setName("B");
        b.start();

    }
}

运行结果:
这里写图片描述

由结果来看,依然是同步进行的,也就是说明了Class锁对所有实例起作用。

同步Synchronized(class) 的实质其实和synchronized static 方法一样,都是给Class加锁。验证:
修改Service代码:

public class Service {
    public void PrintA() {
        synchronized (Service.class) {
            try {
                System.out.println("线程的名称为:" + Thread.currentThread().getName()
                        + "在" + System.currentTimeMillis() + "进入printA");
                Thread.sleep(3000);
                System.out.println("线程的名称为:" + Thread.currentThread().getName()
                        + "在" + System.currentTimeMillis() + "离开printA");
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }

    public  void PrintB() {
        synchronized (Service.class) {
            System.out.println("线程的名称为:" + Thread.currentThread().getName()
                    + "在" + System.currentTimeMillis() + "进入printB");

            System.out.println("线程的名称为:" + Thread.currentThread().getName()
                    + "在" + System.currentTimeMillis() + "离开printB");
        }
    }
}
注意:PrintA和PrintB方法加不加static都一样了这时
再次运行代码得:

这里写图片描述

结论:静态同步synchronized方法与synchronized(class)代码块效果一样,没有本质上的区别,与非静态的方法比起来,非静态的是给对象上锁。多个对象的时候会给多个对象上锁。依旧是异步的。而静态的方法,则因为持有的是Class锁,所以多个对象创建的时候,因为其Class依旧是一样的,所有就会是同步状态

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值