在LinkedList的多线程访问中的线程安全性

时间:2013-07-25 02:19:02

标签: java multithreading concurrency locking

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

我正在考虑使用Locks框架来处理并发处理,我不是最熟悉的,因此这个问题。这是我的代码:

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;
    }
}

我的问题是:

  1. ReentrantLock使用getTrailingStats确保线程安全吗?
  2. 是否需要在synchronized使用锁定?
  3. 我可以使用synchronized块执行所有操作吗?我使用锁的原因是因为我想在R和W部分都有相同的锁,以便写入和读取列表中的第一个元素(最近添加的条目)一次完成一个线程我不能只用{{1}}。
  4. 来做到这一点
  5. 我应该使用ReentrantReadWriteLock吗?

1 个答案:

答案 0 :(得分:3)

锁可能是一个主要的性能瓶颈。另一种方法是使用a ConcurrentLinkedDeque:使用offerFirst添加新元素,并使用(弱一致)iterator(不会抛出ConcurrentModificationException)到位你的每个循环。优点是这将比你的实现或synchronizedList实现更好地执行,但缺点是迭代器是弱一致的 - thread1可能会在列表迭代时将元素添加到列表中,这意味着thread2不会计算这些新元素。但是,这在功能上等同于让thread2锁定列表,以便thread1无法添加它 - 无论是thread2还是不计算新元素。