Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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 多线程访问LinkedList中的线程安全_Java_Multithreading_Concurrency_Locking - Fatal编程技术网

Java 多线程访问LinkedList中的线程安全

Java 多线程访问LinkedList中的线程安全,java,multithreading,concurrency,locking,Java,Multithreading,Concurrency,Locking,我的应用程序需要保留对特定资源请求的访问日志,多个线程将记录日志条目。唯一相关的信息是请求的时间戳,正在检索的统计数据将是在最后X秒内发生的请求数。返回给定秒数的统计信息的方法还需要支持多个线程 我正在考虑使用我不太熟悉的框架来处理并发处理,因此提出了这个问题。这是我的密码: import java.util.LinkedList; import java.util.concurrent.locks.ReentrantLock; public class ConcurrentRecordSta

我的应用程序需要保留对特定资源请求的访问日志,多个线程将记录日志条目。唯一相关的信息是请求的时间戳,正在检索的统计数据将是在最后X秒内发生的请求数。返回给定秒数的统计信息的方法还需要支持多个线程

我正在考虑使用我不太熟悉的框架来处理并发处理,因此提出了这个问题。这是我的密码:

import java.util.LinkedList;
import java.util.concurrent.locks.ReentrantLock;

public class ConcurrentRecordStats 
{
    private LinkedList<Long> recLog;
    private final ReentrantLock lock = new ReentrantLock();

    public LinkedConcurrentStats()
    {
        this.recLog = new LinkedList<Long>();
    }

    //this method will be utilized by multiple clients concurrently
    public void addRecord(int wrkrID)
    {
        long crntTS = System.currentTimeMillis();
        this.lock.lock();
        this.recLog.addFirst(crntTS);
        this.lock.unlock();
    }

    //this method will be utilized by multiple clients concurrently
    public int getTrailingStats(int lastSecs)
    {
        long endTS = System.currentTimeMillis();
        long bgnTS = endTS - (lastSecs * 1000);

        int rslt = 0;

        //acquire the lock only until we have read
        //the first (latest) element in the list
        this.lock.lock();

        for(long crntRec : this.recLog)
        {
            //release the lock upon fetching the first element in the list
            if(this.lock.isLocked()) 
            {
                this.lock.unlock();
            }

            if(crntRec > bgnTS)
            {
                rslt++;
            }
            else
            {
                break;
            }
        }

        return rslt;
    }
}
import java.util.LinkedList;
导入java.util.concurrent.locks.ReentrantLock;
公共类ConcurrentRecordStats
{
私有链接列表重新登录;
private final ReentrantLock lock=new ReentrantLock();
公共链接的ConcurrentStats()
{
this.recLog=new LinkedList();
}
//此方法将由多个客户端同时使用
公共无效添加记录(int wrkrID)
{
长crntTS=System.currentTimeMillis();
this.lock.lock();
this.recLog.addFirst(crntTS);
这个.lock.unlock();
}
//此方法将由多个客户端同时使用
公共int getTrailingStats(int lastSecs)
{
long-endTS=System.currentTimeMillis();
长bgnTS=endTS-(lastSecs*1000);
int rslt=0;
//只有在我们读取之前,才能获取锁
//列表中的第一个(最新)元素
this.lock.lock();
for(长crntRec:this.recLog)
{
//在获取列表中的第一个元素时释放锁
if(this.lock.isLocked())
{
这个.lock.unlock();
}
如果(crntRec>bgnTS)
{
rslt++;
}
其他的
{
打破
}
}
返回rslt;
}
}
我的问题是:

  • 使用
    ReentrantLock
    会确保线程安全吗
  • 是否需要在
    getRailingStats
    中使用锁
  • 我可以使用
    synchronized
    块执行所有这些操作吗?我之所以使用锁,是因为我想在R和W部分中都使用相同的锁,这样列表中第一个元素(最近添加的条目)的写入和读取一次只在一个线程中完成,而仅使用
    synchronized
    无法做到这一点
  • 我应该用这个来代替吗

  • 这些锁可能是一个主要的性能瓶颈。另一种方法是:使用
    offerFirst
    添加新元素,并使用(弱一致的)
    迭代器(不会抛出
    ConcurrentModificationException
    )代替for-each循环。优点是,这将比您的实现或
    synchronizedList
    实现的性能好得多,但缺点是迭代器的一致性很弱-thread1可能会在thread2遍历列表时向列表中添加元素,这意味着thread2不会计算这些新元素。但是,这在功能上相当于让thread2锁定列表,使thread1无法添加到列表中-无论哪种方式,thread2都不会计算新元素。

    我只是想知道,为什么不简单地使用public
    列表集合。synchronizedList(列表列表)
    获取线程安全列表?这会消除锁的需要吗?Java.util.concurrent.ConcurrentLinkedQue使用弱一致迭代器是线程安全的。
    弱一致迭代器的意思是什么?javadoc中有很好的解释:如果T2在T1迭代时添加元素,这不是问题,因为T1不包括新的元素,但我的LinkedList也不会出现
    ConcurrentModificationException
    ,因为我只遍历以前输入的元素,
    getTrailingStats
    中的锁负责在保存第一个现有元素时不插入新元素read@amphibient链表的迭代器不够聪明,无法知道您正在以这样的方式使用它,即对链表的修改无关紧要—它使用一个计数器来计算对链表的修改次数,然后迭代器所做的修改次数,如果这些计数器不匹配,它将抛出一个
    ConcurrentModificationException
    ,这可能发生在您解锁
    锁后,同时仍然通过for-each循环在列表中进行迭代。您需要在整个循环中保持
    ,以避免出现异常。实际上,我模拟了多个线程在其他线程读取时写入,这不会导致异常