java - 大数据模型中的线程安全

标签 java multithreading synchronization thread-safety

背景: 我在内存中有一个(或多或少)巨大的数据模型。该模型包含大约 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) 访问整个数据模型的中央接口(interface)。这个接口(interface)将通过一个锁在每次修改时锁定整个模型。 优点:只有一个锁 --> 更少的同步工作。 缺点:无论更改类型如何,整个模型都被锁定。

(3) 分派(dispatch)线程(类似于 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

当您有大量并发访问时,这通常是一个很好的策略:它具有多种优势:

  • 读者不需要任何锁定。在有很多读者的情况下,这可能是一个巨大的性能胜利。
  • 更新可以自动发生 - 这意味着您绝不会冒读者看到数据处于不一致状态的风险。
  • 您可以随时获取整个数据结构的“快照”。由于不可变数据结构无法更改,您可以随意获取对它的引用,然后随意检查它
  • 更新仍然相对便宜:结构共享意味着您可以在不复制整个数据模型的情况下进行少量更改来制作新版本的数据模型。
  • 您可以拥有适合您要求的各种不同的更新语义。在这种情况下,听起来您有一个“读取和更新”语义以及某种形式的更改通知。

关于java - 大数据模型中的线程安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20016731/

相关文章:

java - 文件未找到异常

java - 如何计算字符串中包含重音符号的元音?

c++ - 在许多不同的平台上使用 c/c++ 中的线程

java - 我是否需要同时同步方法和对象

java - 如何在 JPA 关系中设置被视为 NULL 的值

multithreading - 如何在cocos2d-x的单独线程中加载纹理?

java - AtomicBoolean 没有 negate() 方法吗?

java - 如何使我的 ArrayList 线程安全? Java中解决问题的另一种方法?

server - 桌面应用程序的客户端/服务器状态同步

java - 如何告诉 Eclipse 文件的首选内容类型