一尘不染

在Java关键部分中,应该同步哪些内容?

java

在Java中,在代码中声明关键部分的惯用方式如下:

private void doSomething() {
  // thread-safe code
  synchronized(this) {
    // thread-unsafe code
  }
  // thread-safe code
}

几乎所有块都在上同步 this,但这是否有特定原因?还有其他可能性吗?是否有关于同步对象的最佳实践?(例如Object?的私有实例)


阅读 231

收藏
2020-09-08

共2个答案

一尘不染

首先,请注意以下代码段是相同的。

public void foo() {
    synchronized (this) {
        // do something thread-safe
    }
}

和:

public synchronized void foo() {
    // do something thread-safe
}

完全一样的事情 。除了代码的可读性和样式之外,它们都不是其中之一。

当您同步方法或代码块时,重要的是要知道 为什么 要这样做,要锁定的 对象 到底是 什么,目的什么

还要注意,在某些情况下,您可能需要 客户端同步 代码块,而在这些情况下,您要的监视器(即,同步对象)不一定是必须的this,例如本例:

Vector v = getSomeGlobalVector();
synchronized (v) {
    // some thread-safe operation on the vector
}

我建议您了解有关并发编程的更多知识,一旦您确切了解幕后发生的事情,它将为您提供大量帮助。您应该阅读《Java并行编程》,这是一本关于该主题的好书。如果您想快速了解该主题,请查看Java
Concurrency
@Sun。

2020-09-08
一尘不染

几乎所有块都与此同步,但是是否有特定原因呢?还有其他可能性吗?

该声明使整个方法同步。

private synchronized void doSomething() {

该声明使部分代码块而不是整个方法同步。

private void doSomething() {
  // thread-safe code
  synchronized(this) {
    // thread-unsafe code
  }
  // thread-safe code
}

从oracle文档页面

使这些方法同步有两个效果:

首先,不可能在同一对象上对同步方法的两次调用进行交错。当一个线程正在为对象执行同步方法时,所有其他为同一对象块调用同步方法的线程(挂起执行),直到第一个线程对该对象完成。

还有其他可能性吗?关于要同步的对象,是否有最佳实践?(例如Object的私有实例?)

同步有很多可能性和替代方法。您可以使用高级并发API(自JDK 1.5版本开始提供)使代码线程安全。

Lock objects
Executors
Concurrent collections
Atomic variables
ThreadLocalRandom
2020-10-14