快速背景:当我回过头来重新设计应用程序的一些关键部分时,我一直想知道锁定及其对性能的影响。该应用程序具有大型树样式数据结构,可以从数据库中缓存数据/ DTO。大树的更新可以通过两种主要方式实现:1。用户触发的命令,2。在后台运行的作业的自动更新。
当出现任何一种操作类型(用户/自动)时,我锁定(显式锁定)数据结构。我遇到了一致性问题,因此锁定所有内容似乎最有效地保护了缓存中数据的完整性。
问题:由于许多自动更新可以立即发生我正在考虑实现某种类型的队列(可能是JMS)来处理数据结构的指令,其中任何用户驱动的更新都被推送到顶部并先处理。当涉及到处理批量/未知大小的自动“任务”集合时,我试图弄清楚是否应该让它们单独运行和锁定,或者尝试按时间将它们拼凑在一起并与锁定交互一次。问题的真正症结在于,任何更新任务都可能影响整个树。
就整体性能而言(一般情况下,没有具体说明),让许多事务锁定可能会进行大量更新,或尝试组合到一个大规模批量更新并且只锁定一次但更长时间更有效吗?我知道很多这可能取决于数据,更新的类型,频率等。我不知道是否有一般的经验法则是“更小的更频繁的锁定”或“一个大的可能更长的”锁定。
答案 0 :(得分:1)
如果您最终实现某种类型的队列,那么您将失去所有并发性。如果您一次收到1000个请求,请考虑这是多么低效。
尝试查看此代码以获取并发树。 https://github.com/npgall/concurrent-trees
答案 1 :(得分:1)
我认为答案取决于您的计划是否花费了大量时间解锁数据结构。如果没有,我建议对所有挂起的更新锁定一次。
原因是,当更新线程再次快速锁定资源时,可能正在等待锁定的其他线程可能会被唤醒,然后无用地发送回睡眠状态。或者更新被另一个可能对缓存利用率不利的线程中断。锁定成本与更新相比可能很小:管道可能必须刷新,内存访问可能无法自由重新排序等。
如果线程在更新之间花费一些时间而不必锁定数据结构,我会考虑重新锁定每个更新,如果预期其他线程可以在中间完成其事务并且因此减少争用。
请注意,当我为您的用户更新与后台更新设定的不同更新有不同的优先级时,如果可以在任何时候锁定数据结构很长时间以获得较低优先级的更新,那么这可能是一个坏主意。防止更高优先级的任务运行。