m0_62867495 2023-05-08 07:13 采纳率: 0%
浏览 20

Java中synchronized使用问题

如图所示在编译中使用synchronized关键字之后出现了只有线程Thread-0运行而不见Thread-1 请问是正常情况还是代码出错 求解答

img

img

img

img

  • 写回答

1条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2023-05-08 10:14
    关注
    • 你可以参考下这个问题的回答, 看看是否对你有帮助, 链接: https://ask.csdn.net/questions/7781077
    • 我还给你找了一篇非常好的博客,你可以看看是否有帮助,链接:Java面试题之synchronized关键字原理以及锁相关
    • 除此之外, 这篇博客: Java 多线程同步关键字synchronized各种用法/特性 总结中的 二、synchronized锁静态方法及synchronized(class) 代码块 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
    • 关键字synchronized还可以修饰静态方法,如果修饰静态方法,那就表示给当前Java类进行上锁(也就是Class)。

      用法实例:

      锁静态代码块:

      public static void testSyncStaticBlock() {
         
      synchronized (SyncStaticTest.class) {
              System.
      out.println("锁静态代码块");
          }
      }

       

      锁静态方法:

      synchronized public static void testSyncStaticMethod() {
      
          System.out.println("锁静态方法");
      
      }

       

      给Class类上锁和给this对象上锁是有本质不同的,举个例子说明一下:

      条件:

      假设有一个Java类ClassA, 里面定义了synchronized修饰的静态方法staticMethodA, 和非静态方法methodB。

      用ClassA 创建两个实例ClassObjA 和 ClassObjB。

      创建两个线程threadA和threadB。

      实验:

      1. 用threadA调用classObjA的methodB方法,同时用threadB调用classObjB的methodB方法,发现执行并不是同步的,因为在动态方法中,实例classObjeA的methodB方法的this是指的classObjA,classObjeB的methodB方法this是指的classObjB,上面反复提到过,我们一定要弄清楚对象监视器的指针是指向谁,这很明显是两个对象,压根不存在对象争抢的问题,所以当然不会同步执行。

       

      2. 用threadA和threadB都调用ClassA.staticMethodA方法, 发现是同步执行的,因为synchronized锁的是静态代码块,所以跟对象就没什么关系了,不管哪个线程,只要你调用我ClassA的这个静态方法,都必须排队。

       

      上面两个实验可以很清晰的看到锁class静态代码块和锁对象的区别。

       

      插个广告:下节我们将介绍volatile的各种用法。

       

      参考:

      《Java多线程核心技术》高洪岩著

       

       

       

    • 您还可以看一下 多编程老师的2021版Java多线程教程课程中的 synchronized关键字小节, 巩固相关知识点
    • 以下回答由chatgpt基于相关博客总结生成:

      只有Thread-0线程运行而没有Thread-1线程运行并不是正常现象,很可能是代码出现了问题。使用synchronized关键字可以修饰代码块,形如synchronized(锁对象){...},synchronized关键字需要一个锁对象作为参数,所以每个线程需要拥有该锁对象来进入synchronized代码块。参考资料中的代码中,使用this作为锁对象,每个线程都独立创建了一个Runnable实例,因此锁对象也不同,这违反了使用synchronized关键字的初衷。解决的办法是使用同一个锁对象,比如可以使用static修饰一个Object类型的变量来作为锁对象,示例代码如下:

      static int n = 0;
      static Object lock = new Object();
      public static void main(String[] args) throws InterruptedException {
          Runnable r = new Runnable() {
              @Override
              public void run() {
                  for (int i = 0; i < 10000; i++) {
                      synchronized (lock) {
                          n++;
                      }
                  }
              }
          };
      
          new Thread(r).start();
          new Thread(r).start();
      
          Thread.sleep(3000);
          System.out.println(n);
      }
      

      在这个代码中,使用static Object类型的变量lock作为锁对象,每个线程都使用同一个锁,这样就可以保证两个线程都能够访问synchronized代码块。

    评论

报告相同问题?

问题事件

  • 创建了问题 5月8日

悬赏问题

  • ¥30 seata使用出现报错,其他服务找不到seata
  • ¥15 怎么实现输入一个要删除的数后删除后显示剩余数再输入再删除显示剩余数(语言-c语言)
  • ¥35 引用csv数据文件(4列1800行),通过高斯-赛德尔法拟合曲线,在选取(每五十点取1点)数据,求该数据点的曲率中心。
  • ¥20 程序只发送0X01,串口助手显示不正确,配置看了没有问题115200-8-1-no,如何解决?
  • ¥15 Google speech command 数据集获取
  • ¥15 vue3+element-plus页面崩溃
  • ¥15 像这种代码要怎么跑起来?
  • ¥15 安卓C读取/dev/fastpipe屏幕像素数据
  • ¥15 pyqt5tools安装失败
  • ¥15 mmdetection