ben*_*ben 15 java concurrency multithreading locking
// Not really how java.util.concurrent.Semaphore is implemented
@ThreadSafe
public class SemaphoreOnLock {
private final Lock lock = new ReentrantLock();
// CONDITION PREDICATE: permitsAvailable (permits > 0)
private final Condition permitsAvailable = lock.newCondition();
@GuardedBy("lock") private int permits;
SemaphoreOnLock(int initialPermits) {
lock.lock();
try {
permits = initialPermits;
} finally {
lock.unlock();
}
}
/* other code omitted.... */
Run Code Online (Sandbox Code Playgroud)
我有一个关于上面的示例的问题,该示例是从Java Concurrency中提取的实践清单14.12计算使用Lock实现的信号量.
我想知道为什么我们需要在构造函数中获取锁(如图所示调用lock.lock()).据我所知,构造函数是原子的(除了引用转义),因为没有其他线程可以获得引用,因此,半构造对象对其他线程不可见.因此,我们不需要构造函数的synchronized修饰符.此外,只要对象安全发布,我们也不需要担心内存可见性.
那么,为什么我们需要在构造函数中获取ReentrantLock对象?
Pri*_*ley 12
其他线程看不到半构造对象
这不是真的.如果对象具有任何非final/volatile字段,则在构造时对其他线程可见.因此,其他线程可能会看到permitsie 的默认值,0这可能与当前线程不一致.
Java内存模型为不可变对象(仅包含最终字段的对象)提供了初始化安全性的特殊保证.另一个线程可见的Object引用并不一定意味着该对象的状态对于消费线程是可见的 - JCP $3.5.2
从Java Concurrency in Practice的清单3.15开始:
虽然在构造函数中设置的字段值似乎是写入这些字段的第一个值,因此没有"较旧"的值可以看作是过时值,但是在子类构造函数运行之前,Object构造函数首先将默认值写入所有字段.因此,可以将字段的默认值视为陈旧值.
| 归档时间: |
|
| 查看次数: |
2423 次 |
| 最近记录: |