Synchronized使用情况分析

七种情况分析
1、方法都使用synchronized进行修饰,一个 phone 实例
import java.util.concurrent.TimeUnit;

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

        new Thread(() ->{
            phone.sendMessage();
        }, "threadA").start();

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

        new Thread(() ->{
            phone.callUp();
        }, "threadB").start();
    }
}

class Phone{

    public synchronized void sendMessage(){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }

    public synchronized void callUp(){
        System.out.println("打电话");
    }
}

执行结果:

发短信
打电话

结果分析

为什么先是发短信后是打电话?

原因:synchronized 修饰,锁的是当前调用对象,由于 phone 实例对象只有一个,所以哪个线程先拿到锁,哪个线程先执行

2、方法都使用synchronized进行修饰,两个 phone 实例
import java.util.concurrent.TimeUnit;

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

        new Thread(() ->{
            phone1.sendMessage();
        }, "threadA").start();

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

        new Thread(() ->{
            phone2.callUp();
        }, "threadB").start();
    }
}

class Phone{

    public synchronized void sendMessage(){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }

    public synchronized void callUp(){
        System.out.println("打电话");
    }
}

执行结果:

打电话
发短信

结果分析

为什么先是发打电话后是发短信?

原因:synchronized 修饰,锁的是当前调用对象,由于 phone 实例对象有两个,不存在竞争锁

3、增加了一个普通方法,没有使用 synchronized 修饰
import java.util.concurrent.TimeUnit;

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

        new Thread(() ->{
            phone.sendMessage();
        }, "threadA").start();

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

        new Thread(() ->{
            phone.say();
        }, "threadB").start();
    }
}

class Phone{

    public synchronized void sendMessage(){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }

    public synchronized void callUp(){
        System.out.println("打电话");
    }

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

执行结果:

hello word
发短信

结果分析

为什么先是hello word后是发短信?

原因:synchronized 修饰,锁的是当前调用对象,phone 实例对象虽只有一个,但是普通方法的调用,不需要锁

4、两个静态的同步方法,一个对象调用
import java.util.concurrent.TimeUnit;

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

        new Thread(() ->{
            phone.sendMessage();
        }, "threadA").start();

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

        new Thread(() ->{
            phone.callUp();
        }, "threadB").start();
    }
}

class Phone{

    public static synchronized void sendMessage(){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }

    public static synchronized void callUp(){
        System.out.println("打电话");
    }
}

执行结果:

发短信
打电话

结果分析

为什么先是发短信后是打电话?

原因:static 和 synchronized 修饰,锁的是当前类 class 实例,由于 class 实例是在类加载时创建(Phone.class),只有一个,所以谁先拿到锁,谁先执行(这里和Phone实例对象无关)

可以换种方式理解,主要是 静态属性 or 方法 随着类加载,在内存中只有一份

Class<?> phone1 = Class.forName("Phone");
Class<Phone> phoneClass = Phone.class;
System.out.println(phone1 == phoneClass);

/**
 * 执行结果 true
 * class 实例验证
 */
5、两个静态的同步方法,两个对象调用
import java.util.concurrent.TimeUnit;

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


        new Thread(() ->{
            phone1.sendMessage();
        }, "threadA").start();

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

        new Thread(() ->{
            phone2.callUp();
        }, "threadB").start();
    }
}

class Phone{

    public static synchronized void sendMessage(){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }

    public static synchronized void callUp(){
        System.out.println("打电话");
    }
}

执行结果:

发短信
打电话

结果分析

为什么先是发短信后是打电话?

原因:static 和 synchronized 修饰,锁的是当前类 class 实例,由于 class 实例是在类加载时创建(Phone.class),只有一个,所以谁先拿到锁,谁先执行,这里和多个 Phone 实例无关

6、静态同步方法和普通同步方法,一个对象调用
import java.util.concurrent.TimeUnit;

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

        new Thread(() ->{
            phone.sendMessage();
        }, "threadA").start();

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

        new Thread(() ->{
            phone.callUp();
        }, "threadB").start();
    }
}

class Phone{

    //静态同步方法
    public static synchronized void sendMessage(){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }

    //普通同步方法
    public synchronized void callUp(){
        System.out.println("打电话");
    }
}

执行结果:

打电话
发短信

结果分析

为什么先是发打电话后是发短信?

原因:普通同步方法 和 静态同步方法锁的对象不同,一个是当前调用者实例,一个是 class实例,它们之间没有关系,不影响相互执行

7、 静态同步方法和普通同步方法,两个对象调用
import java.util.concurrent.TimeUnit;

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


        new Thread(() ->{
            phone1.sendMessage();
        }, "threadA").start();

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

        new Thread(() ->{
            phone2.callUp();
        }, "threadB").start();
    }
}

class Phone{

    //静态同步方法
    public static synchronized void sendMessage(){
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("发短信");
    }

    //普通同步方法
    public synchronized void callUp(){
        System.out.println("打电话");
    }
}

执行结果:

打电话
发短信

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值