Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/338.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_Multithreading_Synchronization_Threadpool_Race Condition - Fatal编程技术网

Java 在以下程序中检测和处理竞争条件

Java 在以下程序中检测和处理竞争条件,java,multithreading,synchronization,threadpool,race-condition,Java,Multithreading,Synchronization,Threadpool,Race Condition,我是多线程新手,希望避免在下面的代码中出现争用情况。在release()方法中有一行可用的.add(resource),在remove()方法中有一行可用的.remove(resource)。所以我的问题是如何同步'resource'变量以避免这种竞争条件 package threadpool; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentHashMap;

我是多线程新手,希望避免在下面的代码中出现争用情况。在release()方法中有一行可用的.add(resource),在remove()方法中有一行可用的.remove(resource)。所以我的问题是如何同步'resource'变量以避免这种竞争条件

    package threadpool;
    import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.ConcurrentHashMap;
    import java.util.concurrent.ConcurrentMap;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.LinkedBlockingQueue;
    import java.util.concurrent.TimeUnit;

    public class ResourcePoolImpl<R> implements ResourcePool<R> {

    private static final String CLOSED_POOL_EXCEPTION = "Pool is closed,cannot aquire resource.";

    private static final String  RELEASE_EXCEPTION = "Unaquired resource, cannot release it.";

    private volatile boolean open = false;

    private final BlockingQueue<R> available = new LinkedBlockingQueue<R>();

    private final ConcurrentMap<R, CountDownLatch> aquired = new ConcurrentHashMap<R,  CountDownLatch>();

    public R acquire() throws InterruptedException {
    if ( !open ) { throw new IllegalStateException( CLOSED_POOL_EXCEPTION ); }
    final R resource = available.take();
    if ( resource != null ) {
        aquired.put( resource, new CountDownLatch( 1 ) );
    }
    return resource;
    }


   public R acquire( final long timeout, final TimeUnit timeUnit ) throws InterruptedException {
    if ( !open ) { throw new IllegalStateException( CLOSED_POOL_EXCEPTION ); }

    final R resource = available.poll( timeout, timeUnit );
    if ( resource != null ) {
        aquired.put( resource, new CountDownLatch( 1 ) );
    }
    return resource;
    }


    public boolean add( final R resource ) 
    {
    return available.add( resource );
    } 

    public void close() throws InterruptedException {
    open = false;
    for ( final CountDownLatch latch : aquired.values() ) {
        latch.await();
    }
    }

    public void closeNow() {
    open = false;
    }

    public boolean isOpen() {
    return open;
    }

    public void open() {
    open = true;
    }

    public void release( final R resource ) 
    {
    final CountDownLatch latch = aquired.get( resource );
    if ( latch == null ) { throw new IllegalArgumentException( RELEASE_EXCEPTION ); }
    available.add( resource );
    latch.countDown();
    }

    public boolean remove( final R resource ) throws InterruptedException 
    {   

    final CountDownLatch latch = aquired.get( resource );
    if ( latch != null ) {
        latch.await();
    }
    return available.remove( resource );
    }


    public boolean removeNow( final R resource ) {
    return available.remove( resource );
    }

 }
包线程池;
导入java.util.concurrent.BlockingQueue;
导入java.util.concurrent.ConcurrentHashMap;
导入java.util.concurrent.ConcurrentMap;
导入java.util.concurrent.CountDownLatch;
导入java.util.concurrent.LinkedBlockingQueue;
导入java.util.concurrent.TimeUnit;
公共类ResourcePoolImpl实现ResourcePool{
private static final String CLOSED\u POOL\u EXCEPTION=“池已关闭,无法获取资源。”;
private static final String RELEASE\u EXCEPTION=“非必需资源,无法释放它。”;
private-volatile boolean-open=false;
private final BlockingQueue available=新的LinkedBlockingQueue();
获取的私有最终ConcurrentMap=新ConcurrentHashMap();
public R acquire()抛出InterruptedException{
如果(!open){抛出新的非法状态异常(CLOSED_POOL_EXCEPTION);}
最终R资源=可用。take();
if(资源!=null){
获取.put(资源,新倒计时锁存器(1));
}
返回资源;
}
公共R acquire(最终长超时,最终时间单位)抛出InterruptedException{
如果(!open){抛出新的非法状态异常(CLOSED_POOL_EXCEPTION);}
最终R资源=可用。轮询(超时,时间单位);
if(资源!=null){
获取.put(资源,新倒计时锁存器(1));
}
返回资源;
}
公共布尔加法(最终R资源)
{
返回可用。添加(资源);
} 
public void close()引发InterruptedException{
开=假;
对于(最终倒计时闩锁:aquired.values()){
satch.wait();
}
}
公共空间关闭现在(){
开=假;
}
公共布尔等参元(){
返回打开;
}
公开作废{
开放=真实;
}
公开作废发布(最终R资源)
{
final CountDownLatch-latch=aquired.get(资源);
如果(latch==null){抛出新的IllegalArgumentException(RELEASE_EXCEPTION);}
可用。添加(资源);
倒计时();
}
公共布尔移除(最终R资源)抛出InterruptedException
{   
final CountDownLatch-latch=aquired.get(资源);
如果(闩锁!=null){
satch.wait();
}
返回可用。删除(资源);
}
公共布尔removeNow(最终R资源){
返回可用。删除(资源);
}
}
声明

final Object mutex = new Object();
并让所有对共享集合执行读/写操作的方法在执行操作之前获取互斥锁,或根据共享数据做出决策,并在同步块内执行:

synchronized (mutex) {
     // .. guaranteed single-threaded access here
     //   (for instance, contents of aquire() or release(); 
     //      also add() or any other collection access)
}
然后,您可以使用更简单的非并发集合类,因为在互斥保护区内,不能有任何多线程访问

并发集合只是将它们的访问封装在它们自己的内部互斥锁中——但问题是,正如您在注释中所解释的那样,
获取的
可用的
可能会彼此独立地更新,这是您绝对不希望看到的


因此:通过为所有关键区域访问声明并使用单个互斥来简化代码。

您如何知道您有竞态条件?可用的是BlockingQueue,它是一个并发集合,如果两个线程都在使用它,它应该不会有问题。并发集合只保证put/get是“原子的”;竞争条件可能在此代码之外(例如,您可能同时从两个地方修改资源…)。您确定此代码中存在问题吗?了解您认为此池的行为会很有趣。例如,在上面的代码中,如果不同线程同时调用“release”和“remove”方法,则可能会导致资源在被删除后被添加回池中,这就是我想要避免的。对资源池中的所有方法使用互斥方法怎么样?。让他们每个人在一个互斥体上同步他们的关键区域,你就可以省去所有那些线程安全的集合(因为互斥体将保护他们所有人)。这肯定会有帮助…但我在想一个更好的方法,比如不必在所有方法上不必要地使用synchronize..那么你的意思是说在这种情况下根本不应该有竞争条件?是否由这些集合处理?查看java源代码后,您使用的这些集合依赖于[ReentrantLocks],其语义与synchronized()提供的内置锁非常相似。我无法想象会有任何性能差异;如果有,单互斥版本应该更快(1个锁而不是多个锁)。另外,你可以避免比赛条件。。。