我有一个单进程双线程应用程序。线程1将收听市场数据Feed并更新数千种股票的最新报价。线程2将以采样频率运行计时器,并获取最新报价的快照以进行处理。实际上,我需要对极快的市场数据源进行下采样。</ p>
我对解决方案的第一个猜测是使用BlockingQueue。为此,我需要将计时器功能移动到线程1中,我可以通过每次引用更新时检查时钟并在采样频率上将引号的快照发送到队列来完成。我担心的是队列将消耗大量内存,垃圾收集会减慢速度。
我的第二个猜测是让线程1将数据复制到采样频率的锁定成员,线程2可以访问该数据。我担心的是锁定会很慢。
我的猜想是为了使引用原语易变。由于一个线程只写,一个线程只读,这可能是合适的吗?
对于此延迟敏感的应用程序,是否有最佳实践方式在线程之间传递数据?这不是超高频应用。我可以忍受大约几十毫秒的延迟。
答案 0 :(得分:7)
如果您只有2个线程访问此资源(即不需要并发读取),那么最简单的(也是最快的一个)就是使用lock
关键字:
public class QuoteStore
{
private readonly List<Quote> _quotes = new List<Quote>();
private readonly object _mutex = new object();
public ReadOnlyCollection<Quote> GetQuotes()
{
lock (_mutex)
{
return _quotes.ToReadOnly();
}
}
public void AddQuote()
{
lock (_mutex)
{
_quotes.Add(quote);
}
}
}
如果需要并发读取,这将非常适合the ReaderWriterLockSlim class。复制数据时可以获取读锁定,写入数据时可以获取写锁定,例如:
public class QuoteStore : IDisposable
{
private readonly ReaderWriterLockSlim _mutex = new ReaderWriterLockSlim();
private readonly List<Quote> _quotes = new List<Quote>();
public ReadOnlyCollection<Quote> GetQuotes()
{
_mutex.EnterReadLock();
try
{
return _quotes.ToReadOnly();
}
finally
{
_mutex.ExitReadLock();
}
}
public void AddQuote()
{
_mutex.EnterWriteLock();
try
{
_quotes.Add(quote);
}
finally
{
_mutex.ExitWriteLock();
}
}
public void Dispose()
{
_mutex.Dispose();
}
}
或者,如果您使用.Net 4或更高版本,the System.Collections.Concurrent namespace中有许多可以同时修改的精美集合,您可以使用它们没有任何问题(它们是无锁对象,通常非常快 - 而且{{3 }}!)。
答案 1 :(得分:0)
是不是生产者 - 消费者队列的情况?消费者将等待(Monitor.Wait)生产者在新饲料进入时产生脉冲。一旦新的/更新的饲料进入,生产者将填充队列并激活Monitor.Pulse。