JUC-8锁现象深度剖析

现象一

多个线程使用一把锁,也就是调用同一个对象,顺序执行

“被synchronized修饰的方法,锁的对象是方法的调用者”

public class Test1 {
    public static void main(String[] args) {
        Phone phone = new Phone();

        new Thread(()->{
            phone.sendSms();
        },"A").start();

        //睡眠
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(()->{
            phone.call();
        },"B").start();
    }
}
class Phone{
    public synchronized void sendSms() {
        System.out.println("发短信");
    }
    public synchronized void call() {
        System.out.println("打电话");
    }
}

执行结果:发短信  打电话

 

现象二

多个线程使用同一把锁,其中一个锁方法里存在阻塞,顺序执行

public class Test1 {
    public static void main(String[] args) {
        Phone phone = new Phone();

        new Thread(()->{
            phone.sendSms();
        },"A").start();

        //睡眠
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(()->{
            phone.call();
        },"B").start();
    }
}
class Phone{
    public synchronized void sendSms() {
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }
    public synchronized void call() {
        System.out.println("打电话");
    }
}

执行结果:发短信  打电话

 

现象三

多个线程中既有锁方法,也有普通方法,会随机执行

public class Test1 {
    public static void main(String[] args) {
        Phone phone = new Phone();

        new Thread(()->{
            phone.sendSms();
        },"A").start();
        //睡眠
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(()->{
            phone.call();
        },"B").start();
    }
}
class Phone{
    public synchronized void sendSms() {
        //此阻塞时间长短会对结果产生一定影响,但是理论不变
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }
    public  void call() {
        System.out.println("打电话");
    }
}

执行结果:发短信  打电话

 

现象四

多个线程调用多个对象,多个线程使用多把锁,会随机执行

“Synchronized锁的是方法调用者(即对象),两个线程调用两个不同的对象,所以互不干扰。”

public class Test2 {
    public static void main(String[] args) {
        Phone2 phone1 = new Phone2();
        Phone2 phone2 = new Phone2();

        new Thread(()->{
            phone1.sendSms();
        },"A").start();
        
        //睡眠
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(()->{
            phone2.call();
        },"B").start();
    }
}
class Phone2{
    public synchronized void sendSms() {
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }
    public synchronized void call() {
        System.out.println("打电话");
    }
}

执行结果:发短信  打电话

 

现象五

Class锁,static和Synchronized修饰的方法。

多个线程使用一个对象(一把锁)但是被static修饰,所以锁的是class文,全局只有一个class文,会顺序执行

“被Synchronized和static同时修饰的方法,锁的对象是类的class对象,是唯一的一把锁。线程之间是顺序执行。“

锁class和锁对象的区别:

  1. Class锁:类模板,只有一个;
  2. 对象锁:通过类模板可以new多个对象。
public class Test1 {
    public static void main(String[] args) {
        Phone phone = new Phone();

        new Thread(()->{
            phone.sendSms();
        },"A").start();
        //睡眠
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(()->{
            phone.call();
        },"B").start();
    }
}
class Phone{
    //synchronized锁的是实例对象(即方法的调用者)
    //static 和 synchronized同时修饰 锁的是class
    public static synchronized void sendSms() {
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }
    public static synchronized void call() {
        System.out.println("打电话");
    }
}

执行结果:发短信  打电话

 

现象六

Class锁,static和synchronized修饰的方法。

多个线程使用多个对象(多个锁),可是被static修饰,即锁的是class文,全局只有一个class文,会顺序执行

public class Test1 {
    public static void main(String[] args) {
        Phone phone1 = new Phone();
        Phone phone2 = new Phone();

        new Thread(()->{
            phone1.sendSms();
        },"A").start();
        //睡眠
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(()->{
            phone2.call();
        },"B").start();
    }
}
class Phone{
    //synchronized锁的是实例对象(即方法的调用者)
    //static 和 synchronized同时修饰 锁的是class
    public static synchronized void sendSms() {
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }
    public static synchronized void call() {
        System.out.println("打电话");
    }
}

执行结果:发短信  打电话

 

现象七

一个静态同步方法 ,一个普通同步方法。

多个线程去操作同一个对象,会先执行普通同步方法

“这里虽然只有“一个对象”,但是这“一个对象”调用的方法不同,所以两个线程分别使用两把锁。”

public class Test1 {
    public static void main(String[] args) {
        Phone phone = new Phone();

        new Thread(()->{
            phone.sendSms();
        },"A").start();
        //睡眠
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(()->{
            phone.call();
        },"B").start();
    }
}
class Phone{
    //synchronized锁的是实例对象(即方法的调用者)
    //static 和 synchronized同时修饰 锁的是class
    public static synchronized void sendSms() {
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }
    public  synchronized void call() {
        System.out.println("打电话");
    }
}

执行结果:打电话  发短信

 

现象八

两个静态同步方法,两个对象。

顺序执行

public class Test1 {
    public static void main(String[] args) {
        Phone phone1 = new Phone();
        Phone phone2 = new Phone();

        new Thread(()->{
            phone1.sendSms();
        },"A").start();
        //睡眠
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(()->{
            phone2.call();
        },"B").start();
    }
}
class Phone{
    //synchronized锁的是实例对象(即方法的调用者)
    //static 和 synchronized同时修饰 锁的是class
    public static synchronized void sendSms() {
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }
    public  static synchronized void call() {
        System.out.println("打电话");
    }
}

执行结果:发短信  打电话

 

 

总结:

//被synchronized修饰的方法,锁的对象是实例对象(即方法的调用者)。

//被static synchronized修饰的方法,锁的对象就是class模板对象,这个是全局唯一的。

 

 

  1. synchronized修饰的,多个线程调用单个对象(一把锁)  顺序执行
  2. synchronized修饰的,多个线程调用多个对象(多把锁)  随机执行 

        (注意发短信线程阻塞时间不同会影响结果,阻塞时间长,后执行,反之亦然,而单个对象,即一把锁,无论发短信线程阻塞时间怎            么设置,都是顺序执行)

    //因为synchronized修饰的,锁的是实例对象(方法调用者),所以单个对象的时候谁先调用就谁先拿到锁先执行,而多个对象的时候就看cpu调度,随机执行。  

    3.static synchronized同时修饰的,多个线程调用单个对象,顺序执行。

    4.static synchronized同时修饰的,多个线程调用多个对象,顺序执行。

    //因为static synchronized同时修饰的,锁的是class文,全局唯一,所以单个对象或多个对象调用的时候都是顺序执行。

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值