为什么
不能替代
在订单匹配场景中
高频交易里最常误用的,就是以为加个
就能安全读写共享订单簿。它只保证可见性和禁止重排序,不提供原子性——比如
这种复合操作,哪怕
是
,依然可能丢更新。
真实场景:多个线程同时对
做“取当前值→比较→更新”三步,
完全拦不住竞态
正确做法:用
或
替代锁,比
更轻量,且能保证 CAS 原子性
坑点:
看似方便,但若需更新对象字段(如
),必须用
,否则编译报错
如何让
真正跑满 CPU 而不卡在内存屏障上
的吞吐优势依赖无锁 + 内存预分配,但默认配置下常因缓存行伪共享或序列号等待拖慢——尤其在多生产者往同一 RingBuffer 写入时。
关键配置:必须设
为
(非默认的
),否则线程休眠唤醒开销直接吃掉微秒级优势
伪共享防护:用
标记
中的
、
字段,JVM 启动加
实测差异:某做市商系统将
换成
后,P99 延迟从 18μs 降到 5.2μs,但 CPU 使用率升了 37%,得权衡
在行情解码时为何反而拉高 GC 压力
很多团队用
并行解析 UDP 行情包,背后默认走
。问题在于它的并行度固定为
,且无法回收空闲线程——大量短生命周期的
解析任务会反复触发 G1 的
。
替代方案:显式创建
,设
,并用
开启 asyncMode
更优选择:对纯 CPU 密集型解码(如 FIX/FAST),直接用
缓存
实例 + 固定大小
,避免任务排队和线程切换
典型错误:
中 buffer 若来自堆外内存(
),commonPool 线程未及时清理 cleaner,易触发
Netty 的
和
在断连重试时怎么配才不丢单
交易所网关频繁重建连接时,若内核 TIME_WAIT 连接堆积,新连接可能被拒绝;而
设错又会导致 FIN 包未发完就关闭,订单确认消息直接消失。
Eclipse导入Android或其他的JAVA项目的正确方法 WORD版
本文档主要讲述的是Eclipse导入Android或其他的JAVA项目的正确方法;希望本文档会给有需要的朋友带来帮助;感兴趣的朋友可以过来看看
下载
立即学习
“
Java免费学习笔记(深入)
”;
必须开启,否则端口复用失败,
高频出现
值设为
(即强制 RST 关闭)——高频场景下绝不设正数,否则 linger 期间若对方没收到 ACK,订单状态机就卡死
补充动作:在
事件里主动调用
,把未确认订单转到本地重试队列,别依赖 TCP 可靠性兜底
实际压测发现,低延迟不是堆砌技术点,而是每个环节都得把“内存访问路径”和“内核交互次数”抠到小数点后一位。比如一个
调用,比
快 12ns,但若用错 volatile 语义,这 12ns 全白搭。
volatilesynchronizedvolatileprice = Math.min(price, newPrice)pricevolatileOrderBook.bestAskvolatileAtomicLongFieldUpdaterVarHandle.compareAndSet()synchronizedAtomicIntegerOrder.priceAtomicIntegerFieldUpdaterjava.lang.IllegalAccessExceptionDisruptorDisruptorWaitStrategyBusySpinWaitStrategyBlockingWaitStrategy@ContendedRingBuffercursorgatingSequences-XX:-RestrictContendedYieldingWaitStrategyBusySpinWaitStrategyForkJoinPool.commonPool()CompletableFuture.supplyAsync()ForkJoinPool.commonPool()CPU核心数 - 1ByteBufferG1 Evacuation PauseForkJoinPoolparallelism = Runtime.getRuntime().availableProcessors()new ForkJoinPool(..., true)ThreadLocalDecoderThreadPoolExecutorsupplyAsync(() -> decode(buffer), commonPool)DirectByteBufferjava.lang.OutOfMemoryError: Direct buffer memorySO_REUSEADDRSO_LINGERSO_LINGERSO_REUSEADDR = truejava.net.BindException: Address already in useSO_LINGER0ChannelInactiveorderManager.flushPendingOrders()Unsafe.getAndAddLongAtomicLong.addAndGet()