Java 并发实践 - 示例 14.12 [英] Java Concurrency in Practice - Sample 14.12

查看:16
本文介绍了Java 并发实践 - 示例 14.12的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

// 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.... */

我对上述示例有疑问,该示例摘自 Java 并发实践 清单 14.12 使用锁实现的计数信号量.

I have a question about the sample above which is extracted from Java Concurrency in Practice Listing 14.12 Counting Semaphore Implemented Using Lock.

我想知道为什么我们需要在构造函数中获取锁(如图所示 lock.lock() 被调用).据我所知,构造函数是原子(引用转义除外),因为没有其他线程可以获取引用,因此,其他线程看不到半构造对象.因此,我们不需要构造函数的同步修饰符.此外,我们也不需要担心内存可见性,只要对象安全发布即可.

I am wondering why we need to acquire the lock in the constructor (as shown lock.lock() is invoked). As far as i know, constructor is atomic (except the reference escaped) as no other thread can get the reference, hence, the half-constructed-object is not visible to other threads. Therefore, we do not need the synchronized modifier for constructors. Besides, we do not need to worry about the memory visibility as well, as long as the object is safely published.

那么,为什么我们需要在构造函数中获取 ReentrantLock 对象?

推荐答案

半构造对象对其他线程不可见

the half-constructed-object is not visible to other threads

这不是真的.如果对象具有任何非 final/volatile 字段,则该对象在构造时对其他线程可见.因此,其他线程可能会看到 permits 的默认值,即 0,这可能与当前线程不一致.

It is not true. The object is visible to other threads at the time of construction if it has any non final/volatile fields. Therefore, other threads might see a default value for permits i.e 0 which might not be consistent with the current thread.

Java 内存模型为不可变对象(只有 final 字段的对象)提供了初始化安全的特殊保证.对另一个线程可见的对象引用并不一定意味着该对象的状态对消费线程可见 - JCP $3.5.2

The Java memory model offers a special guarantee of initialization safety for immutable objects (object with only final fields). An object reference visible to another thread does not necessarily mean that the state of that object is visible to the consuming thread - JCP $3.5.2

来自 Java 并发实践的清单 3.15:

From Listing 3.15 of Java Concurrency in Practice:

虽然看起来在构造函数中设置的字段值是写入这些字段的第一个值,因此没有年长"将值视为陈旧值,首先是 Object 构造函数在子类构造函数之前将默认值写入所有字段跑.因此,可以将字段的默认值视为陈旧的值.

While it may seem that field values set in a constructor are the first values written to those fields and therefore that there are no "older" values to see as stale values, the Object constructor first writes the default values to all fields before subclass constructors run. It is therefore possible to see the default value for a field as a stale value.

这篇关于Java 并发实践 - 示例 14.12的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆