你应该同步运行方法吗?为什么或者为什么不?

新手上路,请多包涵

我一直认为在实现 Runnable 的 java 类中同步 run 方法是多余的。 我想弄清楚为什么人们这样做:

 public class ThreadedClass implements Runnable{
    //other stuff
    public synchronized void run(){
        while(true)
             //do some stuff in a thread
        }
    }
}

这似乎是多余和不必要的,因为他们正在为另一个线程获取对象的锁。或者更确切地说,他们明确表示只有一个线程可以访问 run() 方法。但是既然是run方法,它本身不就是自己的线程吗?因此,只有它可以访问自己而不需要单独的锁定机制?

我在网上发现了一个建议,通过同步 run 方法,您可能会创建一个实际的线程队列,例如通过这样做:

  public void createThreadQueue(){
    ThreadedClass a = new ThreadedClass();
    new Thread(a, "First one").start();
    new Thread(a, "Second one, waiting on the first one").start();
    new Thread(a, "Third one, waiting on the other two...").start();
 }

我个人永远不会这样做,但它引出了一个问题,即为什么有人会同步 run 方法。 任何想法为什么或为什么不应该同步运行方法?

原文由 MHP 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 509
2 个回答

同步 run( ) 方法 Runnable 是完全没有意义的 ,除非 你想共享 Runnable 线程 之间 的顺序执行235 -这基本上是自相矛盾的。

理论上还有另一个更复杂的场景,您可能想要同步 run() 方法,这再次涉及在多个线程之间共享 Runnable 但也利用 wait()notify() 。我在 21 多年的 Java 中从未遇到过它。

原文由 user207421 发布,翻译遵循 CC BY-SA 4.0 许可协议

使用 synchronized void blah()void blah() { synchronized(this) { 有 1 个优点,那就是您生成的字节码将短 1 个字节,因为同步将是方法签名的一部分,而不是操作本身。这可能会影响 JIT 编译器内联方法的机会。除此之外没有区别。

最好的选择是使用内部 private final Object lock = new Object() 以防止有人可能锁定您的显示器。它实现了相同的结果,而没有邪恶的外部锁定的缺点。你确实有那个额外的字节,但它很少有什么不同。

所以我会说不,不要在签名中使用 synchronized 关键字。相反,使用类似

public class ThreadedClass implements Runnable{
    private final Object lock = new Object();

    public void run(){
        synchronized(lock) {
            while(true)
                 //do some stuff in a thread
            }
        }
    }
}

编辑回应评论:

考虑一下同步的作用:它防止其他线程进入同一代码块。所以想象一下你有一个像下面这样的类。假设当前大小为 10。有人尝试执行添加,它会强制调整支持数组的大小。当他们正在调整数组大小时,有人在另一个线程上调用了 makeExactSize(5) 。现在突然间你试图访问 data[6] 它突然向你袭来。同步应该可以防止这种情况发生。在多线程程序中,您只需要同步。

 class Stack {
    int[] data = new int[10];
    int pos = 0;

    void add(int inc) {
        if(pos == data.length) {
            int[] tmp = new int[pos*2];
            for(int i = 0; i < pos; i++) tmp[i] = data[i];
            data = tmp;
        }
        data[pos++] = inc;
    }

    int remove() {
        return data[pos--];
    }

    void makeExactSize(int size) {
        int[] tmp = new int[size];
        for(int i = 0; i < size; i++) tmp[i] = data[i];
        data = tmp;
    }
}

原文由 corsiKa 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题