【问题标题】:Java Concurrency ReadWriteLock with my own timestampJava Concurrency ReadWriteLock 与我自己的时间戳
【发布时间】:2016-03-17 05:56:56
【问题描述】:

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)
...

如何设计按外部时间戳排序的读写锁?

【问题讨论】:

  • 从请求中复制它们!
  • 如何将请求中的时间戳放入这些锁中?
  • 您能否对此进行扩展 __ 我需要使用随每个请求一起提供的外部时间戳。__ 您的请求看起来如何?
  • put?key=KEY&value=VALUE&timestamp=TIME get?key=KEY&timestamp=TIME
  • 您应该能够像提取 KEY 一样提取 TIME。您面临的问题是什么?

标签: java concurrency readwritelock


【解决方案1】:

简答:

同步您接收时间戳数据的通道或在接收端使用ConcurrentSkipListMap等有序并发数据结构。同时质疑您是否需要保持这种顺序。

附: ReentrantReadWriteLock 不使用类似的实体(如时间戳)来建立排序,并且其公平调度算法不包括您可以重用的条目的重新排序。 ReentrantReadWriteLock 通过AbstractQueuedSynchronizer 使用基于 CLH 的锁队列。

长答案:

虽然您想要做的事情很可能是您无法避免的事情,但质疑您是否真的需要并发和/或分布式系统中的各种精度和一致性总是好的。

你为什么关心这个问题?

听起来您想通过使用系统中另一层的数据排序来保持公平。您是否需要将这两层分开,可能是因为其中一层不受您的控制,或者因为它们需要在语义上保持分离?如果是这种情况,您可以在这里再问自己几个问题。

是否绝对有必要为每个请求维护此顺序?

这种排序是您业务逻辑的关键部分吗? 它实际上是由你关心的上层的一个组件建立的吗?

  1. 如果它基于某些请求通过您无法控制的网络(如 Internet)到达的时间,您可能并不真正关心此排序,放宽一致性要求可能会导致更高的吞吐量。经常看到,在高度并发、不公平的环境中,不公平置换的请求比在资源利用有问题的公平环境中的请求更快地得到处理。
  2. 如果它是基于一个单一的、超快速的时间戳发布者,它为所有请求建立一个总顺序,您可以修改您的系统,以便时间戳发布者成为为请求提供服务的单一生产者通过 Disruptor 或 ArrayBlockingQueue 进入系统的第二层。

你真的会收到乱序请求吗?

您可能正在解决一个您永远不会真正面临的问题,或者您将在遥远的未来某个地方面临的问题,同时您的时间可以更好地花在其他地方。

如果情况并非如此,并且您实际上希望收到乱序(按照您的外部时间戳顺序)请求,那么您的层之间的通信通道就是在您的系统中引入“无序”的组件之一。这可能是因为有人故意以一致性换取吞吐量,也可能是因为如果不进行额外工作,该通道无法满足您的系统需求。

考虑是更容易在其中强制执行严格的一致性,还是更容易保持原样并在收到请求后对其进行排序。

【讨论】:

    猜你喜欢
    • 2015-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多