多线程访问LinkedList中的线程安全 [英] Thread safety in multithreaded access to LinkedList

查看:1146
本文介绍了多线程访问LinkedList中的线程安全的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

My application needs to keep an access log of requests to a certain resource and multiple threads will be recording log entries. The only pertinent piece of information is the timestamp of the request and the stats being retrieved will be how many requests occurred in the last X seconds. The method that returns the stats for a given number of seconds also needs to support multiple threads.

我当时正在考虑使用锁定框架,我并不是最熟悉的框架,因此是这个问题.这是我的代码:

I was thinking of approaching the concurrency handling using the Locks framework, with which I am not the most familiar, hence this question. Here is my code:

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可以确保线程安全吗?
  2. 是否需要在getTrailingStats中使用锁?
  3. 我可以使用synchronized块来完成所有这些工作吗?我使用锁的原因是因为我想在R和W部分中具有相同的锁,以便一次写入和读取列表中第一个元素(最近添加的条目)的操作,而我仅synchronized不能做到这一点.
  4. 我应该使用 ReentrantReadWriteLock 代替?
  1. Will this use of ReentrantLock insure thread safety?
  2. Is it needed to use a lock in getTrailingStats?
  3. Can I do all this using synchronized blocks? The reason I went with locks is because I wanted to have the same lock in both R and W sections so that both writes and reading of the first element in the list (most recently added entry) is done a single thread at a time and I couldn't do that with just synchronized.
  4. Should I use the ReentrantReadWriteLock instead?

推荐答案

锁可能带来主要的性能瓶颈.一种替代方法是使用 ConcurrentLinkedDeque :使用offerFirst添加一个新元素,并使用(弱一致)iterator(不会抛出ConcurrentModificationException)代替for-each循环.优点是,此方法的性能将比您的实现或synchronizedList实现的性能好得多,但缺点是迭代器的一致性很弱-线程1可能会在迭代线程2的过程中向列表中添加元素,这意味着线程2赢得了不算那些新元素.但是,从功能上讲,这等效于让thread2锁定列表,从而使thread1无法添加到列表中-不管哪种方式,thread2都不会计算新元素.

The locks can present a major performance bottleneck. An alternative is to use a ConcurrentLinkedDeque: use offerFirst to add a new element, and use the (weakly consistent) iterator (that won't throw a ConcurrentModificationException) in place of your for-each loop. The advantage is that this will perform much better than your implementation or than the synchronizedList implementation, but the disadvantage is that the iterator is weakly consistent - thread1 might add elements to the list while thread2 is iterating through it, which means that thread2 won't count those new elements. However, this is functionally equivalent to having thread2 lock the list so that thread1 can't add to it - either way thread2 isn't counting the new elements.

这篇关于多线程访问LinkedList中的线程安全的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆