Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 此非同步对象池实现是否良好/安全?_Java_Synchronization_Lock Free_Pooling - Fatal编程技术网

Java 此非同步对象池实现是否良好/安全?

Java 此非同步对象池实现是否良好/安全?,java,synchronization,lock-free,pooling,Java,Synchronization,Lock Free,Pooling,此对象池是否会导致多线程的可见性问题?我特别想知道这种执行顺序: 线程A-获取对象 线程A-修改对象,比如visibleState=42 线程A-releaseObject 线程B-获取对象获取一个线程刚刚释放的对象 线程A-做一些无关的事情或死亡 线程B-修改对象,让其表示visibleState=1 线程B-打印对象可见状态 线程B-释放对象 在B修改状态本身后,线程A的修改是否可能对线程B可见?我知道这在实践中不会发生,但我不知道JLS/Javadoc是否以及如何保证这一点 下面是代码,只

此对象池是否会导致多线程的可见性问题?我特别想知道这种执行顺序:

线程A-获取对象 线程A-修改对象,比如visibleState=42 线程A-releaseObject 线程B-获取对象获取一个线程刚刚释放的对象 线程A-做一些无关的事情或死亡 线程B-修改对象,让其表示visibleState=1 线程B-打印对象可见状态 线程B-释放对象 在B修改状态本身后,线程A的修改是否可能对线程B可见?我知道这在实践中不会发生,但我不知道JLS/Javadoc是否以及如何保证这一点

下面是代码,只显示基本内容。我省略了泛化和创建对象的工厂

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

public class ObjectPool {

/** Maximum number of objects to be kept in pool */
int maxPoolSize = 10;

/** First object in pool (LIFO queue) */
final AtomicReference<PoolableObject> firstObject = new AtomicReference<PoolableObject>();

/** How many objects are currently in the pool */
final AtomicInteger poolSize = new AtomicInteger();

/** Gets an object from the pool. If no object is available
 * from the pool, a new object is created and returned */
public PoolableObject obtainObject() {
    while (true) {
        PoolableObject object = firstObject.get();
        if (object == null)
            break;
        if (firstObject.compareAndSet(object, object.next)) {
            poolSize.decrementAndGet();
            return object;
        }
    }
    // no more objects in pool, create a new object
    return new PoolableObject();
}

/** Returns an object to the pool. */
public void releaseObject(final PoolableObject object) {
    while (true) {
        if (poolSize.get() >= maxPoolSize)
            break;
        final PoolableObject first = firstObject.get();
        object.next = first;
        if (firstObject.compareAndSet(first, object)) {
            poolSize.incrementAndGet();
            break;
        }
    }
}

}

就能见度而言

在这些属性中,线程在写入易失性变量之前的所有动作都发生在写入之前。或者,换句话说,如果源代码显示一个操作发生在易失性写入之前,那么JITC不能将该操作重新排序为在易失性写入之后发生。因此,问题中引用的场景不会成为问题;在释放对象之前对其所做的更改将对随后捕获该对象的其他线程可见


然而,我并没有完全按照这个池的工作方式,可能还有其他问题。特别是,我不相信firstObject和poolSize之间缺乏原子性是安全的。线程肯定可以看到这些变量处于不一致的状态,因为它们没有同步;不过,我不知道这是否重要。

这里没有真正的队列?你是指firstObject上的评论吗?也许我的英语不好,但我认为一个链表可以被合理地称为“队列”。也许吧,但它不像队列那样被使用。1号的会更容易正确使用,或者a号。你把我弄丢了。第一个对象“指向”列表的第一个对象,它可以是任意长度的。我想我明白了。老实说,虽然…并发性是一个领域,您应该竭尽全力使用预先构建的、已经测试过的抽象,因为很难确定您是否正确。做了和你想做的一样的事情,但是它经过了详尽的测试和优化,并且它的锁定特性已经附上了证据。啊,我确实错过了AtomicReference的“volatile”屏障特性。因此,本质上,A在访问AtomicReference之前执行的任何内存修改都保证在B访问AtomicRef之后对B可见。这完全澄清了我的问题。至于池大小,是的,它与真正的池对象列表不完全同步。出于我的目的,我认为这是不可避免的错误,但唯一的效果应该是,集合池大小没有被准确地遵守,这并不打扰我。@ DurDANAL:可以通过使用AtomicStampedReference来存储FrimeObjor和CyOLSE之间的不一致性的可能性来存储引用和大小。
public class PoolableObject {

/** Links objects in pool in single linked list. */
PoolableObject next;

public int visibleState;

}