Java中synchronized使用问题

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

img

img

img

img

  • 你可以参考下这个问题的回答, 看看是否对你有帮助, 链接: 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代码块。