synchronized 修饰普通方法与静态方法的区别

面试时候被问的问题,当时脑子里闪了一下,但是没答出来

先说结论:

  • synchronized 修饰普通方法时,锁的是当前对象的方法,等价于 synchronized (this)
  • synchronized 修饰静态方法时,锁的是所有对象的方法,等价于 synchronized (Xxx.class)

我们知道,普通方法从属于对象,而静态方法从属于类
带着疑惑,来看代码吧


情景1:当 synchronized 修饰 普通方法后,同一个对象被两个线程调用 结果

public class TestMain {
    public static void main(String[] args) {
        //测试 synchronized 修饰普通方法
        Person person1 = new Person();

        Thread t1 = new Thread() {
            @Override
            public void run() {
                System.out.println("t1开始");
                person1.work("t1线程老板 叫person1 工作啦");
                System.out.println("t1结束");
            }
        };

        Thread t2 = new Thread() {
            @Override
            public void run() {
                System.out.println("t2开始");
                person1.work("t2线程老板 叫person1 工作啦");
                System.out.println("t2结束");
            }
        };
        t1.start();
        t2.start();

    }
}
class Person{

    //输出10次value work 方法
    public synchronized void work(String value){
        for (int i=0;i<10;i++){
            System.out.println(value + i );
            try {
                Thread.sleep(250);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

打印结果

t1开始
t2开始
t1线程老板 叫person1 工作啦0
t1线程老板 叫person1 工作啦1
t1线程老板 叫person1 工作啦2
t1线程老板 叫person1 工作啦3
t1线程老板 叫person1 工作啦4
t1线程老板 叫person1 工作啦5
t1线程老板 叫person1 工作啦6
t1线程老板 叫person1 工作啦7
t1线程老板 叫person1 工作啦8
t1线程老板 叫person1 工作啦9
t1结束
t2线程老板 叫person1 工作啦0
t2线程老板 叫person1 工作啦1
t2线程老板 叫person1 工作啦2
t2线程老板 叫person1 工作啦3
t2线程老板 叫person1 工作啦4
t2线程老板 叫person1 工作啦5
t2线程老板 叫person1 工作啦6
t2线程老板 叫person1 工作啦7
t2线程老板 叫person1 工作啦8
t2线程老板 叫person1 工作啦9
t2结束

上面代码我们可以看到,虽然 t1 和 t2 线程都开始了,但是 t2 线程并没有打断 t1 线程执行wok1 方法 (注意此时都是person1 一个对象)


情景2:synchronized 修饰普通方法后,不同对象被不同的线程调用结果


public class TestMain {
    public static void main(String[] args) {
        //测试 synchronized 修饰普通方法
        Person person1 = new Person();
        Person person2 = new Person();  // 修改 

        Thread t1 = new Thread() {
            @Override
            public void run() {
                System.out.println("t1开始");
                person1.work("t1线程老板 叫person1 工作啦");
                System.out.println("t1结束");
            }
        };

        Thread t2 = new Thread() {
            @Override
            public void run() {
                System.out.println("t2开始");
                person2.work("t2线程老板 叫person2 工作啦"); // 修改
                System.out.println("t2结束");
            }
        };
        t1.start();
        t2.start();

    }
}
class Person{

    //输出10次value work1 方法
    public synchronized void work(String value){
        for (int i=0;i<10;i++){
            System.out.println(value + i );
            try {
                Thread.sleep(250);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

t1开始
t2开始
t1线程老板 叫person1 工作啦0
t2线程老板 叫person2 工作啦0
t1线程老板 叫person1 工作啦1
t2线程老板 叫person2 工作啦1
t2线程老板 叫person2 工作啦2
t1线程老板 叫person1 工作啦2
t1线程老板 叫person1 工作啦3
t2线程老板 叫person2 工作啦3
t1线程老板 叫person1 工作啦4
t2线程老板 叫person2 工作啦4
t2线程老板 叫person2 工作啦5
t1线程老板 叫person1 工作啦5
t1线程老板 叫person1 工作啦6
t2线程老板 叫person2 工作啦6
t2线程老板 叫person2 工作啦7
t1线程老板 叫person1 工作啦7
t1线程老板 叫person1 工作啦8
t2线程老板 叫person2 工作啦8
t1线程老板 叫person1 工作啦9
t2线程老板 叫person2 工作啦9
t2结束
t1结束

我们可以看到 ,这两个对象的方法在执行的过程中 都被打断了


情景3 : 情景2 的基础上 使用 static 修饰work方法

package com.demo06;

public class TestMain {
    public static void main(String[] args) {
        //测试 synchronized 修饰普通方法
        Person person1 = new Person();
        Person person2 = new Person();  // 修改

        Thread t1 = new Thread() {
            @Override
            public void run() {
                System.out.println("t1开始");
                person1.work("t1线程老板 叫person1 工作啦");
                System.out.println("t1结束");
            }
        };

        Thread t2 = new Thread() {
            @Override
            public void run() {
                System.out.println("t2开始");
                person2.work("t2线程老板 叫person2 工作啦"); // 修改
                System.out.println("t2结束");
            }
        };
        t1.start();
        t2.start();

    }
}
class Person{

    //输出10次value work1 方法
    public static synchronized void work(String value){ //改动
        for (int i=0;i<10;i++){
            System.out.println(value + i );
            try {
                Thread.sleep(250);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

t2开始
t2线程老板 叫person2 工作啦0
t1开始
t2线程老板 叫person2 工作啦1
t2线程老板 叫person2 工作啦2
t2线程老板 叫person2 工作啦3
t2线程老板 叫person2 工作啦4
t2线程老板 叫person2 工作啦5
t2线程老板 叫person2 工作啦6
t2线程老板 叫person2 工作啦7
t2线程老板 叫person2 工作啦8
t2线程老板 叫person2 工作啦9
t2结束
t1线程老板 叫person1 工作啦0
t1线程老板 叫person1 工作啦1
t1线程老板 叫person1 工作啦2
t1线程老板 叫person1 工作啦3
t1线程老板 叫person1 工作啦4
t1线程老板 叫person1 工作啦5
t1线程老板 叫person1 工作啦6
t1线程老板 叫person1 工作啦7
t1线程老板 叫person1 工作啦8
t1线程老板 叫person1 工作啦9
t1结束

我们可以看到,两个对象执行方法是又互不打断啦 。

到最后发现,我也可以说成 static 修饰 synchronized 方法后,使这个类的所有实例执行该方法时 都互不中断。synchronized 作用同步了所有的对象

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值