背景:
我在内存中有一个(或多或少)巨大的数据模型.该模型包含大约3.150.000到12.600.000个可以直接修改的对象.此外,大约有75.000.000个对象只能通过3.150.000到12.600.000对象进行修改.
另一方面,大约有10个模块访问模型.这些模块可以分为:
>每250毫秒到1000毫秒读取和修改一些对象
>按需阅读和修改一些对象
>如果已经更改了某些对象,请将其读取
题:
如何同步这样的数据模型?我脑子里有以下想法:
(1)锁定每个可以直接修改的类.
优点:只能锁定已修改的对象.
缺点:高同步工作量和大量锁定实例(3.150.000到12.600.000附加对象/锁).在同步(死锁等)中做错事的风险很大.
(2)访问整个数据模型的*界面.此接口将通过单个锁定锁定整个模型的每个修改.
优点:只有一个锁 – >减少同步工作量.
缺点:无论更改类型如何,整个模型都会被锁定.
(3)调度线程(如在AWT / Swing中).处理任务(事件)的线程.
优点/缺点如想法(2).但是,这将是一个基于事件的解决方案.我阅读了Graham Hamilton关于GUI-tollkits中多线程的文章.此外,John Ousterhout还谈到了“事件与线程”.当然,我的数据模型并不广泛,但文章深入到了问题的核心.
这里链接到Graham Hamilton的文章:https://weblogs.java.net/blog/kgh/archive/2004/10/multithreaded_t.html
那么,你的经历是什么?也许你有一个更好的主意.
编辑:我在对象计算上犯了一个大错误.我刚刚更新了金额.
提前致谢 :)
编辑2:这是我刚刚为演示目的创建的模型:
enum Ware { WOOD, COAL, STONE }
class Stock { Map<Ware, Integer> internalStock; }
class Coordinate { int x; int y; }
interface ILand {}
class World {
Map<Coordinate, ILand> land;
Map<Coordinate, Ship> ships;
}
class Island implements ILand { Stock resources; }
class Ship { Stock stock; }
class Building {Stock stock; }
class Colony implements ILand {
Island builtOn;
Set<Building> building;
}
class Character {
Set<Colony> colonies;
Set<Ship> fleet;
}
这将是数据模型的结构:
Model
World <>--- ILand
<>--- Ship
Character <>--- Colony <>--- Building <>--- Stock
<>--- Island <>---Stock
<>--- Ship <>--- Stock
解决方法:
您可能需要考虑将数据模型转换为不可变的持久数据结构.
这种方法在Scala和Clojure等语言中非常有效.如果您想更好地理解这种技术,以下视频非常值得关注:
http://www.infoq.com/presentations/Value-Identity-State-Rich-Hickey
当您具有重要的并发访问权限时,这通常是一个很好的策略:它具有各种优势:
>读者不需要任何锁定.在有许多读者的情况下,这可以获得巨大的成功.
>更新可以原子方式发生 – 这意味着您永远不会冒着读者看到数据处于不一致状态的风险.
>您可以随时获取整个数据结构的“快照”.由于不可变数据结构无法更改,因此您可以*地获取对它的引用,然后在闲暇时进行检查
>更新仍然相对便宜:结构共享意味着您可以通过一些更改来创建数据模型的新版本,而无需复制整个数据模型.
>您可以拥有各种不同的更新语义,以满足您的要求.在这种情况下,听起来你有一个“读取和更新”语义与某种形式的变更通知相结合.