ReentrantReadWriteLock
非常适合在接收时以编程方式基于时间戳的读写方案。
PUT(KEY=1,VALUE=1)
PUT(KEY=1,VALUE=2)
GET(KEY=1)
PUT(KEY=1,VALUE=1)
...
Java ReentrantReadWriteLock
将根据Java本身提供的时间戳自动同步所有这些内容。
但是,我需要如何使用随每个请求一起提供的外部时间戳。
PUT(KEY=1,VALUE=1,TIMESTAMP=13000000000000)
PUT(KEY=1,VALUE=2,TIMESTAMP=13500000000000)
GET(KEY=1,TIMESTAMP=14000000000000)
PUT(KEY=1,VALUE=1,TIMESTAMP=15000000000000)
...
如何设计外部时间戳排序的ReadWriteLock?
答案 0 :(得分:0)
简答:
同步通过其接收带时间戳数据的通道,或使用接收端上的ConcurrentSkipListMap
等有序并发数据结构。同时质疑你是否需要保持这种排序。
P.S。 ReentrantReadWriteLock
不使用类似时间戳的可比实体来建立排序,其公平调度算法不包括您可以重用的条目的重新排序。 ReentrantReadWriteLock
通过AbstractQueuedSynchronizer
使用基于CLH的锁定队列。
答案很长:
虽然您想要做的事情很可能是您无法避免的事情,但在并发和/或分布式系统中确定您是否真的需要各种精确度和一致性总是很好。
你为什么关心这个问题?
听起来您希望通过使用系统中其他层的数据排序来保持公平性。您是否需要将这两个层分开,可能是因为其中一个层不受您的控制,或者因为它们需要保持语义分离?如果是这种情况,你可以在这里问自己几个问题。
是否必须为每个请求维护此订单?
这种排序是您业务逻辑的重要组成部分吗? 它实际上是由你关心的上层组件建立的吗?
您是否真的收到了无序请求?
你可能正在解决一个你永远不会真正面对的问题,或者你将来会面临某个地方的问题,与此同时,你的时间可能会更好地花在其他地方。
如果情况并非如此,并且您实际上希望收到无序(在您的外部时间戳顺序中)请求,那么您的层之间的通信通道是在您的系统中引入“无序”的组件之一。这可能是因为有人故意想要交换吞吐量的一致性,或者可能是因为没有额外的工作,该渠道不适合您的系统需求。
考虑是否更容易在其中强制执行严格的一致性,或者更容易保持原样,并在收到请求后对其进行排序。
ConcurrentSkipListMap
映射时间戳可能是一个很好的解决方案。如果您不想尝试从论文中应用创意,您可能需要查看Concurrent Programming Without Locks和Fast Concurrent Data-Structures Through
Explicit Timestamping