【问题标题】:Does this require synchronization?这需要同步吗?
【发布时间】:2010-03-07 16:57:23
【问题描述】:

在下面的课程中,我使用的是 singleThreadScheduledExecutor。我的问题是,我是否需要围绕对 dummyInt 和 dummyBoolean 的访问进行同步?

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class Playground {

    /**
     * @param args
     */
    public static void main(String[] args) {
        startThread();

    }

    private static void startThread() {
        ScheduledExecutorService timer = Executors
                .newSingleThreadScheduledExecutor();
        Runnable r = new Runnable() {
            int dummyInt = 0;
            boolean dummyBoolean = false;

            @Override
            public void run() {
                dummyInt = dummyInt + 1;

                if (dummyBoolean) {
                    dummyBoolean= false;
                } else {
                    dummyBoolean= true;
                }

            }

        };

        timer.scheduleAtFixedRate(r, 0, 100, TimeUnit.MILLISECONDS);

    }

}

【问题讨论】:

    标签: java multithreading executorservice


    【解决方案1】:

    不,你没有。只有一个线程访问这些值,因此不需要同步。

    【讨论】:

      【解决方案2】:

      使用该机制启动的每个线程都将拥有自己定义和实例化的“可运行”子类的实例。因此,不可能有争用。

      【讨论】:

        【解决方案3】:

        你需要吗?不,只有一个线程会访问当前实现中的变量,所以它是线程安全的。

        会影响性能吗?嗯,是的,但没有你想象的那么多。现代 JIT 编译器很高兴地发现在当前使用中同步是不必要的,并且几乎消除了编译代码的所有开销——但是会留下一点开销来检查单线程访问的假设是否仍然存在有效的。当然,还有 JITting 的开销。

        不同步会有什么坏处吗?好吧,如果实现发生了变化并且不再支持单线程访问的假设,那么进行更改的开发人员可能会忽略其更改的后果。

        但实际上,在这种情况下,这可能会发生吗?也许不是——所有代码都包含在一个很小的区域中......

        我可能会留下一些评论来记录假设。如果我在项目中的其他任何地方使用JCIP annotations,我什至可以将该类注释为@NotThreadSafe。关于这些注释使用的讨论可以在 Brian Goetz 的 Java Concurrency In Practice 书中找到,注释源代码和 jar 文件可以从本书的 web site 下载。

        【讨论】:

          【解决方案4】:

          你不必成功synchronized

          【讨论】:

            【解决方案5】:

            不,但它可能不会受到伤害。由于您使用的是newSingleThreadScheduledExecutor,它承诺

            任务保证执行 顺序,并且不超过一个 任务将在任何给定时间处于活动状态。

            但如果你改变了执行者,让 Runnable 退出以便其他人可以调用它,或者在外部检查值,那么你会希望你已经同步了它。

            【讨论】:

              【解决方案6】:
              dummyInt = dummyInt + 1;
              

              这个语句实际上是3个独立的操作:

              1. 读取dummyInt的值
              2. 加1
              3. 将值写回 dummyInt

              所以是的,您确实需要同步它。一个线程可以读取该值,然后另一个线程执行所有三个操作,并且当第一个线程完成时,该值仅增加 1(我希望这是有道理的:P)。dummyBoolean 类似。您在 if 语句中读取它并写入新值。

              编辑

              很抱歉没有正确阅读问题。 根据 javadoc,这不需要同步。

              【讨论】:

              • 我知道这是 3 个独立的操作。我问这个的原因是因为我使用的是“singleThreadedExecutor”,所以我认为可能不需要同步。
              • 不,每个线程都会获得它自己的 Runnable 子类实例。
              猜你喜欢
              • 2016-09-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多