synchronized8锁学习总结

文章通过8个不同的示例展示了Java中锁的使用和线程执行顺序。在涉及同步方法的情况下,锁的对象决定了线程的执行次序。当锁对象相同时,线程会有锁的竞争;而锁对象不同时,线程可并发执行。静态同步方法锁定的是类对象,普通同步方法锁定的是实例对象。示例涵盖了不同锁配置下的输出结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

通过8种情况演示锁运行案例,看看我们到底锁的是什么。
输出结果我会放在最底下。可以思考一下,然后对照,代码都是基于Java8运行。

案例:

情况1:标准访问有a b两个线程,请问先打印邮件还是短信 ?

class Phone{
    public  synchronized void sendEmail(){
        
        System.out.println("-------------sendEmail");

    }
    public  synchronized void sendSMS(){
        System.out.println("-------------sendSMS");
    }

}

public class Lock8 {
    public static void main(String[] args) {
        Phone phone = new Phone();
        new Thread(()->{
            phone.sendEmail();
        },"a").start();

        //暂停200ms 保证a先启动
        try {TimeUnit.MILLISECONDS.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}

        new Thread(()->{
            phone.sendSMS();
        },"b").start();

    }
}

情况2:sendEmail故意停3秒?,请问先打印邮件还是短信 ?

class Phone{
    public  synchronized void sendEmail(){
        try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}
        System.out.println("-------------sendEmail");

    }
    public  synchronized void sendSMS(){
        System.out.println("-------------sendSMS");
    }

}

public class Lock8 {
    public static void main(String[] args) {
        Phone phone = new Phone();
        new Thread(()->{
            phone.sendEmail();
        },"a").start();

        //暂停200ms 保证a先启动
        try {TimeUnit.MILLISECONDS.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}

        new Thread(()->{
            phone.sendSMS();
        },"b").start();

    }
}

情况3:添加一个普通的hello方法,请问先打印邮件还是hello

class Phone{
    public  synchronized void sendEmail(){
        try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}
        System.out.println("-------------sendEmail");

    }
    public  synchronized void sendSMS(){
        System.out.println("-------------sendSMS");
    }

    public void hello(){
        System.out.println("---------hello");
    }

}

public class Lock8 {
    public static void main(String[] args) {
        Phone phone = new Phone();
        new Thread(()->{
            phone.sendEmail();
        },"a").start();

        //暂停200ms 保证a先启动
        try {TimeUnit.MILLISECONDS.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}

        new Thread(()->{
            phone.hello();
        },"b").start();

    }
}

情况4:有2部phone , 请问先打印邮件还是短信 ?

class Phone{
    public  synchronized void sendEmail(){
        try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}
        System.out.println("-------------sendEmail");

    }
    public  synchronized void sendSMS(){
        System.out.println("-------------sendSMS");
    }

    public void hello(){
        System.out.println("---------hello");
    }

}

public class Lock8 {
    public static void main(String[] args) {
        Phone phone = new Phone();
        Phone phone2 = new Phone();
        
        new Thread(()->{
            phone.sendEmail();
        },"a").start();

        //暂停200ms 保证a先启动
        try {TimeUnit.MILLISECONDS.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}

        new Thread(()->{
            phone2.sendSMS();
        },"b").start();

    }
}

情况5:有2个静态同步方法,有一部phone ,请问先打印邮件还是短信 ?

class Phone{
    public  static synchronized void sendEmail(){
        try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}
        System.out.println("-------------sendEmail");

    }
    public  static synchronized void sendSMS(){
        System.out.println("-------------sendSMS");
    }

    public void hello(){
        System.out.println("---------hello");
    }

}

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


        new Thread(()->{
            phone.sendEmail();
        },"a").start();

        //暂停200ms 保证a先启动
        try {TimeUnit.MILLISECONDS.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}

        new Thread(()->{
            phone.sendSMS();
        },"b").start();

    }
}

情况6:有2个静态同步方法,有两部phone,请问先打印邮件还是短信 ?


class Phone{
    public  static synchronized void sendEmail(){
        try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}
        System.out.println("-------------sendEmail");

    }
    public  static synchronized void sendSMS(){
        System.out.println("-------------sendSMS");
    }

    public void hello(){
        System.out.println("---------hello");
    }

}

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


        new Thread(()->{
            phone.sendEmail();
        },"a").start();

        //暂停200ms 保证a先启动
        try {TimeUnit.MILLISECONDS.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}

        new Thread(()->{
            phone2.sendSMS();
        },"b").start();

    }
}

情况7:有1个静态同步方法,1个普通同步方法,有1部phone_,_请问先打印邮件还是短信 ?

class Phone{
    public  static synchronized void sendEmail(){
        try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}
        System.out.println("-------------sendEmail");

    }
    public   synchronized void sendSMS(){
        System.out.println("-------------sendSMS");
    }

    public void hello(){
        System.out.println("---------hello");
    }

}

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



        new Thread(()->{
            phone.sendEmail();
        },"a").start();

        //暂停200ms 保证a先启动
        try {TimeUnit.MILLISECONDS.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}

        new Thread(()->{
            phone.sendSMS();
        },"b").start();

    }
}

情况8:有1个静态同步方法,1个普通同步方法,有2部phone_,_请问先打印邮件还是短信 ?

class Phone{
    public  static synchronized void sendEmail(){
        try {TimeUnit.SECONDS.sleep(3);} catch (InterruptedException e) {e.printStackTrace();}
        System.out.println("-------------sendEmail");

    }
    public   synchronized void sendSMS(){
        System.out.println("-------------sendSMS");
    }

    public void hello(){
        System.out.println("---------hello");
    }

}

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


        new Thread(()->{
            phone.sendEmail();
        },"a").start();

        //暂停200ms 保证a先启动
        try {TimeUnit.MILLISECONDS.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}

        new Thread(()->{
            phone2.sendSMS();
        },"b").start();

    }
}

锁的说明:

对于被synchronize关键字修饰普通方法。锁是this。
对于被synchronize关键字修饰static方法。锁是类对象。
对于同步方法块。锁的是synchronize(xxx)括号内的对象。
如果锁对象不同,就不会产生锁的竞争。

8种情况解释说明:

情况1,2:
sendEmail 和sendSMS 都是同步方法。而且锁对象都是phone。所以会产生竞争,从代码执行顺序来看,
sendEmail 先执行,那就先获得锁。sendSMS 则等待sendEmail 执行完毕。
情况3:
hello是个普通方法并未和synchronize修饰的sendEmail方法产生锁的争抢。但sendEmail中睡了3秒,所以hello先输出。
情况4:
有两个phone锁对象,sendEmail 和 sendSMS没有锁的竞争。但sendEmail中睡了3秒,所以sendSMS先输出。
情况5,6:
sendEmail 和 sendSMS 都是静态同步方法,锁对象都是当前类对象。sendEmail 会先抢到锁,sendSMS 进行等待。sendEmail先执行。
情况7:
sendEmail 是静态同步方法,锁对象都是当前类对象。sendSMS 是普通同步方法,锁对象是this。两者没有锁的竞争。但sendEmail中睡了3秒,所以sendSMS先输出。
情况8:
虽然有两个phone对象,但是道理还是和情况7一样。

运行结果:

情况1:

-------------sendEmail
-------------sendSMS

情况2:

-------------sendEmail
-------------sendSMS

情况3:

---------hello
-------------sendEmail

情况4:

-------------sendSMS
-------------sendEmail

情况5:

-------------sendEmail
-------------sendSMS

情况6:

-------------sendEmail
-------------sendSMS

情况7:

-------------sendSMS
-------------sendEmail

情况8:

-------------sendSMS
-------------sendEmail

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值