Intrinsic Locks and Synchronization

Intrinsic Locks and Synchronization
内置锁和同步
Synchronization is built around an internal entity known as the intrinsic lock or monitor lock. (The API specification often refers to this entity simply as a "monitor.") Intrinsic locks play a role in both aspects of synchronization: enforcing exclusive access to an object's state and establishing happens-before relationships that are essential to visibility.
同步是建立在一种被称作intrinsic lock或monitor lock的内部实体上的。(API specification 通常在引用这个实体时简称为onitor”)内置锁对同步有俩个作用:
对象状态的互斥性访问和建立happens-before对可见性是基础

Every object has an intrinsic lock associated with it. By convention, a thread that needs exclusive and consistent access to an object's fields has to acquire the object's intrinsic lock before accessing them, and then release the intrinsic lock when it's done with them. A thread is said to own the intrinsic lock between the time it has acquired the lock and released the lock. As long as a thread owns an intrinsic lock, no other thread can acquire the same lock. The other thread will block when it attempts to acquire the lock.
When a thread releases an intrinsic lock, a happens-before relationship is established between that action and any subsequent acquistion of the same lock.
每个对象都有一个内置锁(intrinsic lock)。一般,线程互斥一致的访问对象的字段需要在访问前获得对象的内置锁(intrinsic lock),当它完成了对字段的操作就会
释放锁。一个线程在获得锁和释放锁的时间内可以说拥有这个锁。只要线程拥有这个锁,其他的线程就不恩那个获得相同的锁,其他的线程试图获得锁时会被阻塞(block
当一个线程释放锁,就会与随后相同锁的获得建立一种happens-before关系

Locks In Synchronized Methods同步方法中的锁
When a thread invokes a synchronized method, it automatically acquires the intrinsic lock for that method's object and releases it when the method returns. The lock release occurs even if the return was caused by an uncaught exception.
当一个线程调用一个同步方法,它会自动为方法对象获取一个锁并且当方法返回时释放掉锁。即使是通过一个不可捕获的异常返回也会释放掉锁
You might wonder what happens when a static synchronized method is invoked, since a static method is associated with a class, not an object. In this case, the thread acquires the intrinsic lock for the Class object associated with the class. Thus access to class's static fields is controlled by a lock that's distinct from the lock for any instance of the class.
你可能想知道当一个静态同步方法调用会发生什么,因为静态方法是与类关联的,不是与对象。在 这种情况下线程会为与类关联的类对象获得锁,因此对类的静态字段的访问会受这个锁的控制,它与任何类的实例的锁都不同。

Synchronized Statements同步语句
Another way to create synchronized code is with synchronized statements. Unlike synchronized methods, synchronized statements must specify the object that provides the intrinsic lock:
另外一种创建同步代码的方法是使用同步语句。不像同步方法,同步语句必须指定一个提供锁的对象

public void addName(String name) {
synchronized(this) {
lastName = name;
nameCount++;
}
nameList.add(name);
}
In this example, the addName method needs to synchronize changes to lastName and nameCount, but also needs to avoid synchronizing invocations of other objects' methods. (Invoking other objects' methods from synchronized code can create problems that are described in the section on Liveness.) Without synchronized statements, there would have to be a separate, unsynchronized method for the sole purpose of invoking nameList.add.
在这个例子中addName方法必须同步对lastName和nameCount的改变。但是需要避免同步其他对象方法的调用(在同步块中调用其他对象方法会产生下一章会讨论的活性问题)。同步语句外面,为了调用nameList.add必须有一个单独的,非同步方法
Synchronized statements are also useful for improving concurrency with fine-grained synchronization. Suppose, for example, class MsLunch has two instance fields, c1 and c2, that are never used together. All updates of these fields must be synchronized, but there's no reason to prevent an update of c1 from being interleaved with an update of c2 — and doing so reduces concurrency by creating unnecessary blocking. Instead of using synchronized methods or otherwise using the lock associated with this, we create two objects solely to provide locks.
同步语句对改善并发的细粒度同步(fine-grained synchronization)也有效果。假设,例如类MsLunch有2个字段c1和c2,它们永远不会同时使用。所有对于这俩个字段的更新必须同步,但是没有理由防止c1的更新夹在c2的更新之间。这样做只是导致了不必要的阻塞减少了并发。我们创建2个的单独的对象提供锁而不是使用同步方法或与this关联的锁
public class MsLunch {
private long c1 = 0;
private long c2 = 0;
private Object lock1 = new Object();
private Object lock2 = new Object();

public void inc1() {
synchronized(lock1) {
c1++;
}
}

public void inc2() {
synchronized(lock2) {
c2++;
}
}
}
Use this idiom with extreme care. You must be absolutely sure that it really is safe to interleave access of the affected fields.
使用这个方法必须格外小心。你必须绝对确定交替访问受影响的字段是安全的
Reentrant Synchronization
可重入的同步
Recall that a thread cannot acquire a lock owned by another thread. But a thread can acquire a lock that it already owns. Allowing a thread to acquire the same lock more than once enables reentrant synchronization. This describes a situation where synchronized code, directly or indirectly, invokes a method that also contains synchronized code, and both sets of code use the same lock. Without reentrant synchronization, synchronized code would have to take many additional precautions to avoid having a thread cause itself to block.
回忆一下一个线程不能获得被令一个线程拥有的锁。但是一个线程能够获得它已经有的锁。允许一个线程多次获得同样的锁使同步能够可重入,这描述了这样一种情况,在同步代码里直接或间接调用包含同步代码的方法,这俩组代码会使用相同的锁。没有可重入同步(reentrant synchronization),同步代码会采用许多额外的注意事项来避免线程导致它自己被阻塞

原文地址:https://www.cnblogs.com/yuwenxing/p/2517219.html