【问题标题】:Lock on object's field value锁定对象的字段值
【发布时间】:2018-08-13 14:43:55
【问题描述】:

我的微服务正在接收来自 rabbitMQ 的消息并将其存储在 CouchDB 中, 我正在创建多个消费者线程来处理它们,并且我的代码由于正在发生的竞争条件而引发 ConflictUpdateException,即

线程X、Y同时读取同一个Object的couch db值;线程 X 在线程 Y 之前更新了 Couch 中的记录,但是线程 Y 正在根据 X 之前的哈希值 (_rev) 更新记录 修改记录。

对象的唯一标识符是复合的:name+age+id,

如何只为相同的线程执行临界区 (姓名+年龄+身份证)?

我不想实现的可能方式:

  1. 锁定字符串值(姓名 + 年龄 + id)。 [作为一种不好的做法]

  2. 用于锁定的 String 和 CustomObjects 的 HashMap。 [因为我没有唯一对象计数的内存限制]

有什么建议吗?

【问题讨论】:

    标签: java multithreading performance


    【解决方案1】:

    我认为你应该跟踪_rev:

    • 检索文档,记下 CouchDB 发送的 _rev 属性
    • 编辑您需要的字段
    • 使用 _rev 属性将更新后的文档发回
    • 如果 _rev 与当前存储的数字匹配,则完成!
    • 如果存在冲突(当 _rev 不匹配时),请检索最新的文档版本并再次编辑您需要编辑的内容。转到第 3 步

    【讨论】:

      【解决方案2】:

      你需要concurrentHashMap 结构,持有锁定的主键。 它们的表示由您决定,不鼓励的字符串与实现 hashcode+equals 的某些专用类的实例一样好。 您的消费者将遍历输入队列,尝试通过调用原子 putIfAbsent() 来锁定记录。如果成功,它将执行其 storeToDatabase() 调用,然后从该映射中进行 remove() 条目。否则移动到队列中的下一个条目。

      通过这种方式,您将只需要在此锁定键映射中的少数(消费者计数)条目, 没有巨大的内存消耗,并行度会很高。但它不会保留传入的订单。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多