java - 将 : Spilitting compound, 非原子操作锁定为更简单的原子操作

标签 java multithreading lock-free atomic

我正在编写一个金融市场数据分发应用程序,作为我的硕士项目的一部分。应用程序即将完成,但应用程序的扩展性不佳。

这就是它的工作原理,我订阅了一个“假”交易所来获取市场数据。 订阅后,我得到一个初始快照,然后我不断收到增量......

1) Subscribe for IBM.
2) Snapshot : Buy:50|Size:1400||Sell:49|Size:1000
(At buy price of 50, 1400 shares and at sell price of 49, 1000 shares available)
3) Update1: -1|10||-2|25
(Buy price is now 49 (50-1), buy Size is 1410. Sell price is 47 and sell size is 1025)
4) Update2 ...
.
.
.

我有一个处理市场数据的类,下面的 dataUpdate() 是“假”交换应用程序在一个线程中调用的回调方法。

class MarketDataProcessor:
Map<String, MarketData> marketDataMap      = new HashMap<String, MarketData>(1000);
ConcurrentMap<String, MarketData> distMap  = new ConcurrentHashMap<String, MarketData>();

//**Always called by one thread (MarketDataThread)**
    public void dataUpdate( MarketDataUpdate dataUpdate ){

            try{
                 //IBM
                 String symbol   = dataUpdate .getSymbol();             
                 MarketData data = marketDataMap.get( symbol );

                 if ( data = null ){
                    data = new MarketData( dataUpdate );
                 }else{
                    //Apply the delta here and save it ...
                    marketDataMap.put( symbol, data );
                 }

                 distMap.put( symbol, data );

            }catch( Exception e ){
               LOGGER.warn("Exception while processing market data.");
               LOGGER.warn("Exception: {}", e);
            }
    }

从交易所获取市场数据后,我需要以线程安全的方式分发它。 该方法扩展性较差,因为它可以由 20 个以上的线程调用,并且使用外部锁来确保原子性。

public final double[] getData( String symbol, Side side ){
     double[] dataArray = {0.0, 0.0};

     synchronized( LOCK ){
        MarketData data = distMap.get( symbol );
        dataArray       = ( side == BUY ) ? getBuyData(data) : getSellData(data); 
     }

  return dataArray;
}

这是我建议的解决方案,即将上述方法一分为二。

//No external lock as it uses a ConcurrentHashMap
public final MarketData getData( String symbol ){
       return distMap.get( symbol );
}

//State of this method is now confimed to the
//stack of the calling thread, therefore thread safe.
public final double[] getData( MarketData data, Side side ){
       return ( side == BUY ) ? getBuyData(data) : getSellData(data); 
}

承认这会改变 api 并使用户调用两个方法而不是一个方法,那么在不使用外部锁的情况下是否不会使其成为线程安全的?

谢谢。

最佳答案

将许多线程转储到单个同步线程中并不是一个好主意,这需要时间。

您能否将这些结果转储到同步队列中以便稍后分析?单个线程可以将项目从队列中取出,同时许多线程将其放入队列中。

关于java - 将 : Spilitting compound, 非原子操作锁定为更简单的原子操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15420136/

相关文章:

java - 访问 ="permitAll"和过滤器 ="none"之间的区别?

c++ - std::lock()定义不正确,无法实现还是没用?

java - 如何在 java 中使用 DMA 或 RDMA?

c# - 在这种情况下是否需要锁定?

java - 数组排序方法行为

c++ - 在C++ 11中是否有任何等于asm (“”::: “memory”)的编译器障碍?

c - 单读单写固定大小的ringbuf,没有锁和原子变量,对于任何CPU架构来说总是安全的吗?

go - 确保 Go channel 不阻塞的可靠方法

java - R xlsx 包错误

java - iText 的 getPageN() 和 getPageNRelease() 调用有什么区别?