繁体   English   中英

何时在Java中使用synchronized

[英]When to use synchronized in Java

我希望这将是足够的信息,所以在这里。 如果您需要更多信息,请在评论中了解。

我有一个有两个内部类的类。 内部类每个都有两个方法来调用外部类中的方法。 所以,它看起来像这样:

public OuterClass {
    private boolean outerMethodHasBeenCalled = false;

    private void outerMethod() {
        if(!outerMethodHasBeenCalled) {
            // do stuff
        }

        outerMethodHasBeenCalled = true;
    }

    private FirstInnerClass {
        public void someMethod() {
            outerMethod();
        }
    }

    private SecondInnerClass {
        public void someOtherMethod() {
            outerMethod();
        }
    }
}

重要的是要注意:

  • 这适用于Android应用。 FirstInnerClassSecondInnerClass实例作为JavaScript接口传递给WebView,因此可以随时调用someMethodsomeOtherMethod ,没有特定的顺序。
  • 我现在的代码(没有synchronized关键字)存在问题,其中outerMethod几乎在同一时间被调用(我打印出一条日志消息,并且它们被加时间戳到1000秒)由不同的对象。 我的应用程序,然后“并不东西”两次,因为outerMethodHasBeenCalled仍然是假的时outerMethod被调用。 这不好,这正是我想要阻止的。 我的应用程序应该只执行一次“只做一次”:第一次outerMethod
  • 听起来我可能有多个OuterClass实例,但请放心,它只是OuterClass的一个实例。

重要的是,只有第一次outerMethod时,我的应用程序才会“填充”(我希望现在可以看出这一点)。 所有后续调用基本上都被忽略。 无论哪个内部类首先调用outerMethod - 都无关紧要。

那么,在这种情况下使用synchronized关键字是否合适?

是的,鉴于你上面列出的内容,我会选择:

private synchronized void outerMethod() {
...
}

注意,这将产生阻止其中一个调用者的副作用,直到outerMethod()完成。 如果这是可以接受的,很酷。 如果意图仅仅是outerMethod()中的代码运行一次, 并且如果第一个调用者运行outerMethod(),则第二个调用者没有延迟是可以的,您可以考虑:

public OuterClass {
    private AtomicBoolean outerMethodHasBeenCalled = new AtomicBoolean();

    private void outerMethod() {
        if (outerMethodHasBeenCalled.compareAndSet(false, true)) {
            // do stuff
        }
    }
...

请参阅JavaDoc for AtomicBoolean以了解其中发生的事情(假设它在Android的Java中可用)。

将您想在同步块中只运行一次的outerMethod中的所有内容包装:

private void outerMethod() {
    synchronized (this) {
        if(!outerMethodHasBeenCalled) {
            // do stuff
        }

        outerMethodHasBeenCalled = true;
    }
}

这样,第一次调用该方法时,一次只允许一个线程进入同步块。 第一个将在if语句中执行代码,然后将outerMethodHasBeenCalled设置为true 其他线程将看到它是真的,并跳过if代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM