• 系列七、线程8锁


    一、锁一

    1.1、资源类Phone1

    1. /**
    2. * @Author : 一叶浮萍归大海
    3. * @Date: 2023/11/20 14:03
    4. * @Description: 资源类
    5. */
    6. public class Phone1 {
    7. /**
    8. * 发短信
    9. */
    10. public synchronized void sendMessage() {
    11. System.out.println("===============>sendMessage");
    12. }
    13. /**
    14. * 发邮件
    15. */
    16. public synchronized void sendEmail() {
    17. System.out.println("===============>sendEmail");
    18. }
    19. }

    1.2、线程类Lock8Demo1

    1. /**
    2. * @Author : 一叶浮萍归大海
    3. * @Date: 2023/11/20 14:06
    4. * @Description: 线程8锁
    5. * 问题:标准访问,先打印短信还是先打印邮件
    6. */
    7. public class Lock8Demo1 {
    8. public static void main(String[] args) throws InterruptedException {
    9. Phone1 phone1 = new Phone1();
    10. new Thread(() -> {
    11. try {
    12. phone1.sendMessage();
    13. } catch (Exception e) {
    14. e.printStackTrace();
    15. }
    16. }, "AA").start();
    17. Thread.sleep(100);
    18. new Thread(() -> {
    19. try {
    20. phone1.sendEmail();
    21. } catch (Exception e) {
    22. e.printStackTrace();
    23. }
    24. }, "BB").start();
    25. }
    26. }

    1.3、分析

            一个对象里面如果有多个synchronized方法,某一个时刻内,只要有一个线程调用其中的一个synchronized方法了,其它的线程都只能等待,换句话说,某一个时刻内,只能有唯一一个线程去访问这些synchronized方法。此时锁的是当前对象this,被锁定后,其它的线程都不能进入到当前对象的其它的synchronized方法。

    二、锁二

    2.1、资源类

    1. /**
    2. * @Author : 一叶浮萍归大海
    3. * @Date: 2023/11/20 14:03
    4. * @Description: 资源类
    5. */
    6. public class Phone2 {
    7. /**
    8. * 发短信
    9. */
    10. public synchronized void sendMessage() {
    11. // 线程休眠(单位:秒)
    12. try { TimeUnit.SECONDS.sleep(4); } catch (Exception e) {e.printStackTrace();}
    13. System.out.println("===============>sendMessage");
    14. }
    15. /**
    16. * 发邮件
    17. */
    18. public synchronized void sendEmail() {
    19. System.out.println("===============>sendEmail");
    20. }
    21. }

    2.2、线程类

    1. /**
    2. * @Author : 一叶浮萍归大海
    3. * @Date: 2023/11/20 14:06
    4. * @Description: 线程8锁
    5. * 问题:
    6. * 1、标准访问,先打印短信还是先打印邮件
    7. * 2、短信停4秒,先打印短信还是打印邮件
    8. */
    9. public class Lock8Demo2 {
    10. public static void main(String[] args) throws InterruptedException {
    11. Phone2 phone2 = new Phone2();
    12. System.out.println(Thread.currentThread().getName());
    13. new Thread(() -> {
    14. try {
    15. phone2.sendMessage();
    16. } catch (Exception e) {
    17. e.printStackTrace();
    18. }
    19. }, "AA").start();
    20. Thread.sleep(100);
    21. new Thread(() -> {
    22. try {
    23. phone2.sendEmail();
    24. } catch (Exception e) {
    25. e.printStackTrace();
    26. }
    27. }, "BB").start();
    28. }
    29. }

    2.3、分析

            一个对象里面如果有多个synchronized方法,某一个时刻内,只要有一个线程调用其中的一个synchronized方法了,其它的线程都只能等待,换句话说,某一个时刻内,只能有唯一一个线程去访问这些synchronized方法。此时锁的是当前对象this,被锁定后,其它的线程都不能进入到当前对象的其它的synchronized方法。

    三、锁三

    3.1、资源类

    1. /**
    2. * @Author : 一叶浮萍归大海
    3. * @Date: 2023/11/20 14:03
    4. * @Description: 资源类
    5. */
    6. public class Phone3 {
    7. /**
    8. * 发短信
    9. */
    10. public synchronized void sendMessage() {
    11. // 线程休眠(单位:秒)
    12. try { TimeUnit.SECONDS.sleep(4); } catch (Exception e) {e.printStackTrace();}
    13. System.out.println("===============>sendMessage");
    14. }
    15. /**
    16. * 发邮件
    17. */
    18. public synchronized void sendEmail() {
    19. System.out.println("===============>sendEmail");
    20. }
    21. /**
    22. * 打招呼
    23. */
    24. public void sayHello() {
    25. System.out.println("===============>sayHello");
    26. }
    27. }

    3.2、线程类

    1. /**
    2. * @Author : 一叶浮萍归大海
    3. * @Date: 2023/11/20 14:06
    4. * @Description: 线程8锁
    5. * 问题:
    6. * 1、标准访问,先打印短信还是先打印邮件
    7. * 2、短信停4秒,先打印短信还是打印邮件
    8. * 3、新增普通的hello方法,是先打短信还是hello
    9. */
    10. public class Lock8Demo3 {
    11. public static void main(String[] args) throws InterruptedException {
    12. Phone3 phone3 = new Phone3();
    13. System.out.println(Thread.currentThread().getName());
    14. new Thread(() -> {
    15. try {
    16. phone3.sendMessage();
    17. } catch (Exception e) {
    18. e.printStackTrace();
    19. }
    20. }, "AA").start();
    21. Thread.sleep(100);
    22. new Thread(() -> {
    23. try {
    24. phone3.sayHello();
    25. } catch (Exception e) {
    26. e.printStackTrace();
    27. }
    28. }, "BB").start();
    29. }
    30. }

    3.3、分析

    普通方法和同步锁没有关系。

    四、锁四

    4.1、资源类

    1. /**
    2. * @Author : 一叶浮萍归大海
    3. * @Date: 2023/11/20 14:03
    4. * @Description: 资源类
    5. */
    6. public class Phone4 {
    7. /**
    8. * 发短信
    9. */
    10. public synchronized void sendMessage() {
    11. // 线程休眠(单位:秒)
    12. try { TimeUnit.SECONDS.sleep(4); } catch (Exception e) {e.printStackTrace();}
    13. System.out.println("===============>sendMessage");
    14. }
    15. /**
    16. * 发邮件
    17. */
    18. public synchronized void sendEmail() {
    19. System.out.println("===============>sendEmail");
    20. }
    21. }

    4.2、线程类

    1. /**
    2. * @Author : 一叶浮萍归大海
    3. * @Date: 2023/11/20 14:06
    4. * @Description: 线程8锁
    5. * 问题:
    6. * 1、标准访问,先打印短信还是先打印邮件
    7. * 2、短信停4秒,先打印短信还是打印邮件
    8. * 3、新增普通的hello方法,是先打短信还是hello
    9. * 4、现在有两部手机,先打印短信还是邮件
    10. */
    11. public class Lock8Demo4 {
    12. public static void main(String[] args) throws InterruptedException {
    13. Phone4 phone1 = new Phone4();
    14. Phone4 phone2 = new Phone4();
    15. System.out.println(Thread.currentThread().getName());
    16. new Thread(() -> {
    17. try {
    18. phone1.sendMessage();
    19. } catch (Exception e) {
    20. e.printStackTrace();
    21. }
    22. }, "AA").start();
    23. Thread.sleep(100);
    24. new Thread(() -> {
    25. try {
    26. phone2.sendEmail();
    27. } catch (Exception e) {
    28. e.printStackTrace();
    29. }
    30. }, "BB").start();
    31. }
    32. }

    4.3、分析

    phone1和phone2锁的是2把不同的锁。

    五、锁五

    5.1、资源类

    1. /**
    2. * @Author : 一叶浮萍归大海
    3. * @Date: 2023/11/20 14:03
    4. * @Description: 资源类
    5. */
    6. public class Phone5 {
    7. /**
    8. * 发短信
    9. */
    10. public static synchronized void sendMessage() {
    11. // 线程休眠(单位:秒)
    12. try { TimeUnit.SECONDS.sleep(4); } catch (Exception e) {e.printStackTrace();}
    13. System.out.println("===============>sendMessage");
    14. }
    15. /**
    16. * 发邮件
    17. */
    18. public static synchronized void sendEmail() {
    19. System.out.println("===============>sendEmail");
    20. }
    21. }

    5.2、线程类

    1. /**
    2. * @Author : 一叶浮萍归大海
    3. * @Date: 2023/11/20 14:06
    4. * @Description: 线程8锁
    5. * 问题:
    6. * 1、标准访问,先打印短信还是先打印邮件
    7. * 2、短信停4秒,先打印短信还是打印邮件
    8. * 3、新增普通的hello方法,是先打短信还是hello
    9. * 4、现在有两部手机,先打印短信还是邮件
    10. * 5、两个静态同步方法,1部手机,先打印短信还是邮件
    11. */
    12. public class Lock8Demo5 {
    13. public static void main(String[] args) throws InterruptedException {
    14. System.out.println(Thread.currentThread().getName());
    15. Phone5 phone1 = new Phone5();
    16. new Thread(() -> {
    17. try {
    18. phone1.sendMessage();
    19. } catch (Exception e) {
    20. e.printStackTrace();
    21. }
    22. }, "AA").start();
    23. Thread.sleep(100);
    24. new Thread(() -> {
    25. try {
    26. phone1.sendEmail();
    27. } catch (Exception e) {
    28. e.printStackTrace();
    29. }
    30. }, "BB").start();
    31. }
    32. }

    5.3、分析

    所有的静态同步方法用的是同一把锁,即类对象本身。

    六、锁六

    6.1、资源类

    1. /**
    2. * @Author : 一叶浮萍归大海
    3. * @Date: 2023/11/20 14:03
    4. * @Description: 资源类
    5. */
    6. public class Phone6 {
    7. /**
    8. * 发短信
    9. */
    10. public static synchronized void sendMessage() {
    11. // 线程休眠(单位:秒)
    12. try { TimeUnit.SECONDS.sleep(4); } catch (Exception e) {e.printStackTrace();}
    13. System.out.println("===============>sendMessage");
    14. }
    15. /**
    16. * 发邮件
    17. */
    18. public static synchronized void sendEmail() {
    19. System.out.println("===============>sendEmail");
    20. }
    21. }

    6.2、线程类

    1. /**
    2. * @Author : 一叶浮萍归大海
    3. * @Date: 2023/11/20 14:06
    4. * @Description: 线程8锁
    5. * 问题:
    6. * 1、标准访问,先打印短信还是先打印邮件
    7. * 2、短信停4秒,先打印短信还是打印邮件
    8. * 3、新增普通的hello方法,是先打短信还是hello
    9. * 4、现在有两部手机,先打印短信还是邮件
    10. * 5、两个静态同步方法,1部手机,先打印短信还是邮件
    11. * 6、两个静态同步方法,2部手机,先打印短信还是邮件
    12. */
    13. public class Lock8Demo6 {
    14. public static void main(String[] args) throws InterruptedException {
    15. System.out.println(Thread.currentThread().getName());
    16. Phone6 phone1 = new Phone6();
    17. Phone6 phone2 = new Phone6();
    18. new Thread(() -> {
    19. try {
    20. phone1.sendMessage();
    21. } catch (Exception e) {
    22. e.printStackTrace();
    23. }
    24. }, "AA").start();
    25. Thread.sleep(100);
    26. new Thread(() -> {
    27. try {
    28. phone2.sendEmail();
    29. } catch (Exception e) {
    30. e.printStackTrace();
    31. }
    32. }, "BB").start();
    33. }
    34. }

    6.3、分析

    所有的静态同步方法用的是同一把锁,即类对象本身。

    七、锁七

    7.1、资源类

    1. /**
    2. * @Author : 一叶浮萍归大海
    3. * @Date: 2023/11/20 14:03
    4. * @Description: 资源类
    5. */
    6. public class Phone7 {
    7. /**
    8. * 发短信
    9. */
    10. public static synchronized void sendMessage() {
    11. // 线程休眠(单位:秒)
    12. try { TimeUnit.SECONDS.sleep(4); } catch (Exception e) {e.printStackTrace();}
    13. System.out.println("===============>sendMessage");
    14. }
    15. /**
    16. * 发邮件
    17. */
    18. public synchronized void sendEmail() {
    19. System.out.println("===============>sendEmail");
    20. }
    21. }

    7.2、线程类

    1. /**
    2. * @Author : 一叶浮萍归大海
    3. * @Date: 2023/11/20 14:06
    4. * @Description: 线程8锁
    5. * 问题:
    6. * 1、标准访问,先打印短信还是先打印邮件
    7. * 2、短信停4秒,先打印短信还是打印邮件
    8. * 3、新增普通的hello方法,是先打短信还是hello
    9. * 4、现在有两部手机,先打印短信还是邮件
    10. * 5、两个静态同步方法,1部手机,先打印短信还是邮件
    11. * 6、两个静态同步方法,2部手机,先打印短信还是邮件
    12. * 7、一个静态同步方法,一个普通同步方法,1部手机,先打印短信还是邮件
    13. */
    14. public class Lock8Demo7 {
    15. public static void main(String[] args) throws InterruptedException {
    16. System.out.println(Thread.currentThread().getName());
    17. Phone7 phone7 = new Phone7();
    18. new Thread(() -> {
    19. try {
    20. phone7.sendMessage();
    21. } catch (Exception e) {
    22. e.printStackTrace();
    23. }
    24. }, "AA").start();
    25. Thread.sleep(100);
    26. new Thread(() -> {
    27. try {
    28. phone7.sendEmail();
    29. } catch (Exception e) {
    30. e.printStackTrace();
    31. }
    32. }, "BB").start();
    33. }
    34. }

    7.3、分析

    sendMessage锁的是类对象本身,sendEmail锁的是当前对象本身,两者锁的不是同一个对象,所以不会存在竞争条件。

    八、锁八

    8.1、资源类

    1. /**
    2. * @Author : 一叶浮萍归大海
    3. * @Date: 2023/11/20 14:03
    4. * @Description: 资源类
    5. */
    6. public class Phone8 {
    7. /**
    8. * 发短信
    9. */
    10. public static synchronized void sendMessage() {
    11. // 线程休眠(单位:秒)
    12. try { TimeUnit.SECONDS.sleep(4); } catch (Exception e) {e.printStackTrace();}
    13. System.out.println("===============>sendMessage");
    14. }
    15. /**
    16. * 发邮件
    17. */
    18. public synchronized void sendEmail() {
    19. System.out.println("===============>sendEmail");
    20. }
    21. }

    8.2、线程类

    1. /**
    2. * @Author : 一叶浮萍归大海
    3. * @Date: 2023/11/20 14:06
    4. * @Description: 线程8锁
    5. * 问题:
    6. * 1、标准访问,先打印短信还是先打印邮件
    7. * 2、短信停4秒,先打印短信还是打印邮件
    8. * 3、新增普通的hello方法,是先打短信还是hello
    9. * 4、现在有两部手机,先打印短信还是邮件
    10. * 5、两个静态同步方法,1部手机,先打印短信还是邮件
    11. * 6、两个静态同步方法,2部手机,先打印短信还是邮件
    12. * 7、一个静态同步方法,一个普通同步方法,1部手机,先打印短信还是邮件
    13. * 8、一个静态同步方法,一个普通同步方法,2部手机,先打印短信还是邮件
    14. */
    15. public class Lock8Demo8 {
    16. public static void main(String[] args) throws InterruptedException {
    17. System.out.println(Thread.currentThread().getName());
    18. Phone8 phone1 = new Phone8();
    19. Phone8 phone2 = new Phone8();
    20. new Thread(() -> {
    21. try {
    22. phone1.sendMessage();
    23. } catch (Exception e) {
    24. e.printStackTrace();
    25. }
    26. }, "AA").start();
    27. Thread.sleep(100);
    28. new Thread(() -> {
    29. try {
    30. phone2.sendEmail();
    31. } catch (Exception e) {
    32. e.printStackTrace();
    33. }
    34. }, "BB").start();
    35. }
    36. }

    8.3、分析

    sendMessage锁的是类对象本身,sendEmail锁的是当前对象本身,两者锁的不是同一个对象,所以不会存在竞争条件。

    九、总结

    synchronized实现同步的基础:Java中的每一个对象都可以作为锁


    具体表现为以下3种形式。
            对于普通同步方法,锁是当前实例对象。
            对于静态同步方法,锁是当前类的Class对象。
            对于同步方法块,锁是synchonized括号里配置的对象

            当一个线程试图访问同步代码块时,它首先必须得到锁,退出或抛出异常时必须释放锁。也就是说如果一个实例对象的非静态同步方法获取锁后,该实例对象的其他非静态同步方法必须等待获取锁的方法释放锁后才能获取锁,可是别的实例对象的非静态同步方法因为跟该实例对象的非静态同步方法用的是不同的锁,所以毋须等待该实例对象已获取锁的非静态同步方法释放锁就可以获取他们自己的锁。所有的静态同步方法用的也是同一把锁——类对象本身,这两把锁是两个不同的对象,所以静态同步方法与非静态同步方法之间是不会有竞态条件的。但是一旦一个静态同步方法获取锁后,其他的静态同步方法都必须等待该方法释放锁后才能获取锁,而不管是同一个实例对象的静态同步方法之间,还是不同的实例对象的静态同步方法之间,只要它们同一个类的实例对象!

  • 相关阅读:
    任务四 机器学习库Scikit-learn
    【C++STL基础入门】list的增、删
    conda 实践
    【Docker】从零开始:2.Docker三要素
    如何在react项目中使用Echarts
    园子的融资计划:最困难的时候偶遇最对的合伙人
    PerfView专题 (第十一篇):使用 Diff 功能洞察 C# 内存泄漏增量
    【Unity实战】实现强大通用易扩展的对话系统(附项目源码)
    FPGA领域顶级学术会议
    windows CMD命令的一些使用方法及注意事项
  • 原文地址:https://blog.csdn.net/HelloWorld20161112/article/details/134506863