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

问题描述

  //不是真的如何实现java.util.concurrent.Semaphore 
@ThreadSafe
public class SemaphoreOnLock {
private final Lock lock = new ReentrantLock();
//条件预测:permitsAvailable(许可> 0)
私有最终条件permitsAvailable = lock.newCondition();
@GuardedBy(lock)private int permits;

SemaphoreOnLock(int initialPermits){
lock.lock();
try {
permits = initialPermits;
} finally {
lock.unlock();
}
}

/ *其他代码省略.... * /

我有一个关于从实践中的Java并发中抽取的示例的问题。清单14.12计数使用锁实现的信号量。



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



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

解决方案

这不是真的。如果其他线程具有任何非最终/易失性字段,则对象在构建时对其他线程可见。因此,其他线程可能会看到 permits 0 的默认值,这可能与当前线程不一致。 / p>

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



从代码3.15中的Java Concurrency in Practice:


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

I have a question about the sample above which is extracted from Java Concurrency in Practice Listing 14.12 Counting Semaphore Implemented Using 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.

So, why do we need to get the ReentrantLock object inside the constructor?

解决方案

It is not true. 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 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

From Listing 3.15 of Java Concurrency in Practice:

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

09-21 02:18