3

假设您有一个仅在同步块中调用的方法 foo()。

正在制作方法

synchronized void foo() {..}

与只是

void foo() {..}

多余的或不好的做法,还是使方法的意图更清晰?在方法签名上使用 synchronized 关键字会使程序变慢吗?我想知道更好的做法是什么,或者我是否错过了大局的一部分。

谢谢。

4

3 回答 3

1

这不是多余的,实际上在你已经持有的锁上同步是相当普遍的。

在什么是线程安全和什么不是线程安全之间有明确定义的 API 更容易使用,最好的边界可能是在类级别。因此,如果该类的其余部分是线程安全的,并且 foo() 方法在同步时也是线程安全的,那么您也可以这样做并在您的类文档中记录下来。如果同步 foo() 会给你一个混合了线程安全和非线程安全调用的 API,那么这将在以后导致混乱。

关于性能,我怀疑这将是一个问题(无争议的锁应该有最小的开销)。让代码工作,然后看看你是否需要让它更快。

于 2013-02-12T21:09:39.137 回答
1

通常,这意味着foo()它本身不是原子动作,它可能不保留不变量,它只是更宏大的同步方案的一部分。

那么它不应该声明synchronized否则读者可能会得到错误的想法;它也有点慢。

相反,你可以

void foo()
{
    assert Thread.holdsLock(this);
    ...
}

它有两个目的

  1. 说明此方法只能在外部synchonized(this)块中调用
  2. 在运行时检查该要求(我将为所有非生产运行启用断言)
于 2013-02-12T18:55:48.480 回答
0

我想您的foo()方法在 A 类中,而调用者代码(在同步块中调用它)在另一个 B 类中。

我的建议是不要创建 A 的方法synchronized,因为在单线程程序中调用会系统性地变慢。

正如您所指出的,最好使用同步块使客户端类(例如B)执行同步作业。

总之,我的建议是不要声明同步方法,因为它更灵活:您可以使用带有外部同步块的类来制作线程安全的程序,也可以制作快速的单线程应用程序。您还可以警告您的用户您的 A 类不是线程安全的。

于 2013-02-12T19:50:20.450 回答