java - 同步发生了一些奇怪的事情(Test2.class)

标签 java multithreading static java-threads synchronized-block

public class Test2 {
    static int count;
    public static void main(String[] args) {
        final Test2 t1 = new Test2();
        final Test2 t2 = new Test2();

        new Thread(new Runnable() {

            @Override
            public void run() {
                t1.foo();
            }
        }).start();

        new Thread(new Runnable() {

            @Override
            public void run() {
                t1.bar();
            }
        }).start();

        new Thread(new Runnable() {

            @Override
            public void run() {
                t2.foo();
            }
        }).start();
    }
    public static synchronized void foo() {
        synchronized (Test2.class) {
            System.out.println("run bar"+count++);
            try {
                Thread.sleep(100000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    public static synchronized void bar() {
        System.out.println("run bar");
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

上面是我尝试过的代码。当我在一个同步类(Test2.class)中编写所有代码时,我发现发生了一些奇怪的事情。在调用 foo() 方法后,我无法立即调用 bar() 方法。我认为它锁定了同一个对象。如何解释这个奇怪的事情。

最佳答案

您的代码启动的所有 3 个线程都在 Test2 类上获取相同的锁。当您编写以

开头的方法时
static synchronized

这意味着它必须获取类对象的锁。

foo 方法中的同步块(synchronized block)是多余的。它指定使用与使用静态同步相同的类来锁定。由于内在锁是可重入的,这不会导致问题。

无论如何,每个线程都会获取锁,运行完成,然后释放锁。由于您锁定的是类而不是实例,因此您的线程使用 Test2 的哪个实例并不重要,它们仍然获取相同的锁并一次执行一个。

当我运行此命令时,我得到以下输出:

c:\Users\ndh>java Test2
run bar0
run bar1
run bar

这些线程运行的顺序取决于调度程序。猜测调用 t1.foo 的 Runnable 抢先一步似乎是合理的——因为它是首先创建并启动的,所以很可能有一个窗口,在该窗口中不会有任何竞争获取锁。

关于java - 同步发生了一些奇怪的事情(Test2.class),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41545492/

相关文章:

c++ - 为什么我的线程执行在 CPU 内核之间跳跃?

image - 检测谷歌地图街景静态图片的 "we have no imagery"

html - 我想在 Express.js 中渲染静态 html,但仍然有 app.get() 逻辑方法

python - 在获取静态 django 文件时收到 404 错误

java - servlet 可以有扩展吗?

java - 无法在 tomcat 8 中部署 spring boot app (1.2.5) war

Netbeans 8.1 中的 Java Web

java - 如何使用 Java 和 OpenOffice UNO API 操作 odt 文件中的嵌入文件

C# 隐藏程序定时器

java - 一个线程计时比其他线程快