原子加载存储价格
Atomic Load Store Price
题目详情
在低延迟交易系统中,行情由专用生产者线程摄入,由策略线程消费,无需传统锁的开销。为最小化延迟和避免竞争条件,量化开发者使用带适当内存序的原子操作传递最新价格。
任务:实现 AtomicPrice 类,使用 std::atomic<double> 存储最新价格。生产者使用 release 内存序 store() 更新价格,消费者使用 acquire 内存序 load() 读取价格,确保消费者总是看到最新值。
英文原题
In low-latency trading systems, market data is typically ingested by a dedicated producer thread and consumed by trading strategy threads without the overhead of traditional locks. To minimize latency and avoid race conditions, quantitative developers utilize atomic variables with specific memory ordering constraints to safely publish and read price updates.
Task
Implement a class AtomicPricePublisher that uses std::atomic to safely publish and read the latest best-bid price across multiple thr
解析
问题分析
在多线程交易系统中,最新成交价需要被多个线程无锁读取。使用 std::atomic<double> 确保写的可见性和读的原子性。写入使用 store,读取使用 load——简单高效。
实现
class AtomicPrice {
std::atomic<double> last_price_{0.0};
std::atomic<uint64_t> last_update_ns_{0};
public:
void update(double price, uint64_t timestamp_ns) {
last_update_ns_.store(timestamp_ns, std::memory_order_release);
last_price_.store(price, std::memory_order_release);
}
std::pair<double, uint64_t> get() const {
uint64_t ts = last_update_ns_.load(std::memory_order_acquire);
double px = last_price_.load(std::memory_order_acquire);
return {px, ts};
}
};复杂度与边界
- 时间复杂度:update/get O(1),无锁
- 空间复杂度:O(1)
- 边界条件:(1) 读写窗口期内价格和时间戳可能不配对 (2) 使用 memory_order_release/acquire 保证写顺序 (3) 浮点 store 在某些平台非原子——C++20 保证
英文解析
Analysis
In a multi-threaded trading system, the latest trade price must be read lock-free by multiple threads. Using std::atomic<double> ensures write visibility and read atomicity. Writing uses store, reading uses load - simple and efficient.
Solution
class AtomicPrice {
std::atomic<double> last_price_{0.0};
std::atomic<uint64_t> last_update_ns_{0};
public:
void update(double price, uint64_t timestamp_ns) {
last_update_ns_.store(timestamp_ns, std::memory_order_release);
last_price_.store(price, std::memory_order_release);
}
std::pair<double, uint64_t> get() const {
uint64_t ts = last_update_ns_.load(std::memory_order_acquire);
double px = last_price_.load(std::memory_order_acquire);
return {px, ts};
}
};Complexity & Edge Cases
- Time complexity: update/get O(1), lock-free
- Space complexity: O(1)
- Edge cases: (1) Price and timestamp may be unpaired within a read window (2) memory_order_release/acquire ensures write ordering (3) Floating-point store is non-atomic on some platforms - C++20 guarantees atomicity
Verification
Concurrent writers update price, readers verify they always get a valid price-timestamp pair (possibly stale but never torn). Confirm no partial writes observed.
Key Considerations
Atomic load/store is the simplest concurrency primitive for price dissemination. In market data systems, the release/acquire ordering ensures that when a reader sees a new price, it also sees the corresponding timestamp - critical for time-series consistency.