The Java™ Tutorials — Concurrency :Synchronized Methods 同步方法
原文地址:https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
关键点
- 效果:获取一个对象的锁。因此同一时刻同一实例的多个同步方法中,仅一个处在可执行态。
- 使用方法:在方法定义中使用synchronized关键字
- 功能:在并发环境中,为多个线程针对同一方法的调用建立先行关系
全文翻译
The Java programming language provides two basic synchronization idioms: synchronized methods and synchronized statements. The more complex of the two, synchronized statements, are described in the next section. This section is about synchronized methods.
Java提供了两种同步方式:同步方法和同步语句。同步语句这个较复杂的方式我们将在下节讨论。本章节我们关注同步方法。
To make a method synchronized, simply add the synchronized keyword to its declaration:
为了让方法同步,你只需在其定义中加入同步关键字:
public class SynchronizedCounter {
private int c = 0;
public synchronized void increment() {
c++;
}
public synchronized void decrement() {
c--;
}
public synchronized int value() {
return c;
}
}
If count is an instance of SynchronizedCounter, then making these methods synchronized has two effects:
- First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
- Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.
如果count是一个SynchronizedCounter的实例,那么让这些方法同步会产生两种效果:
- 首先,对同一对象的同步方法的调用是不可能交错进行的。当一个线程正在执行某对象的同步方法时,其他所有尝试调用此方法的线程都会被阻塞,直到第一个线程完成操作。
- 第二,当一个同步方法退出时,它会自动地,和任何随后在同一对象上对它的调用建立先行关系。这保证了对此对象状态的改变对其他线程是可见的。
Note that constructors cannot be synchronized — using the synchronized keyword with a constructor is a syntax error. Synchronizing constructors doesn’t make sense, because only the thread that creates an object should have access to it while it is being constructed.
注意,构造器是无法被同步的,为构造器使用synchronized关键字总会造成语法错误。同步构造器是没有任何意义的,因为只有那些正在创建对象的线程才会调用构造器。
Warning: When constructing an object that will be shared between threads, be very careful that a reference to the object does not “leak” prematurely. For example, suppose you want to maintain a List called instances containing every instance of class. You might be tempted to add the following line to your constructor:
注意:当创建一个将要被两个线程共享的对象时,请务必当心,不要把对象的引用过早地泄露。例如,假设持有一个名为instances的,且包含了所有类实例的列表,你也许会将下面这行添加到构造方法中去:
instances.add(this);
But then other threads can use instances to access the object before construction of the object is complete.
但是其他线程可以在此实例构造完成前,利用instances访问到这个对象。
Synchronized methods enable a simple strategy for preventing thread interference and memory consistency errors: if an object is visible to more than one thread, all reads or writes to that object’s variables are done through synchronized methods. (An important exception: final fields, which cannot be modified after the object is constructed, can be safely read through non-synchronized methods, once the object is constructed) This strategy is effective, but can present problems with liveness, as we’ll see later in this lesson.
同步方法为避免内存冲突以及内存一致性错误提供了一种简单的策略:如果一个对象被多个线程共享,那么对此对象的变量的读写就可以通过同步方法完成。(不过有一个重要的例外:final变量,它是不能在对象构造完成后进行修改的。也就是说,在对象构造完成后,通过同步方法仅可对其进行安全的读取。)此策略非常有效,正如我们将要在随后课时中所见的那样,它可以避免很多有关线程活跃度的问题。