"日记"或"交易"设计模式?

Ric*_*ket 8 oop design-patterns transactions

我正在寻找实现一个记录的对象,或者在其中有一个持久的事务.也就是说,对象包含数据(可能是Map).当对数据进行更改时,这些更改将单独保存,如果您愿意,则为沙箱,以便任何外部对象都可以引用基本状态(在更改之前)或可以访问最新数据.然后还有另一个操作将更改提交到基本状态.

它让我想起了Linux日志文件系统.文件系统更改将写入日志,并且稍后将提交到永久存储中.

它也许更类似于关系数据库世界中"事务"的概念; 也就是说,你有一些数据,你开始一个事务并以某种方式操纵数据.并发进程将查看旧数据,而不进行任何更改.然后,您可以"回滚"事务,或"提交"您的更改.

我特别想在Java中实现它,但显然它是一个通用的面向对象模式,如果它甚至存在.我希望它至少可以创建,但我并不十分确定实现它的最佳方法.

此外,假设对象包含大量数据,整个层次结构(子对象等).因此,不能只保留整个数据树的两个副本; 它会非常浪费内存,复制操作(提交时)会花费太长时间.我希望在游戏的上下文中实现这一点,每帧一次提交操作,所以它确实需要是最佳的.

Jef*_*dge 7

The best way to achieve what you want is to make the object and all of its subobjects immutable. Then the two threads can operate on them without any conflicts, and you don't have to maintain two copies of everything. The only things that would require two copies are the things that actually change, and those can be very small.

Suppose object A is composed of objects B and C. Object B is composed of objects D and E. And object C is composed of objects F and G. So A, B, and C are each just two pointers, and D, E, F, and G are whatever they are.

First you create your initial instance and give it to both threads.

ThreadOne -> A1{ B1{ D1, E1 } C1{ F1, G1 } } 
ThreadTwo -> A1{ B1{ D1, E1 } C1{ F1, G1 } } 
Run Code Online (Sandbox Code Playgroud)

So both threads are pointing at the same instance, no additional memory is consumed, and there are no threading issues, because the objects do not ever change.

Now ThreadOne needs to modify object F. To do this, it just creates a new F, a new C to contain it, and a new A to contain the new C. The original B, D, E, and G are unchanged, and do not need to be copied.

ThreadOne -> A2{ B1{ D1, E1 } C2{ F2, G1 } } 
ThreadTwo -> A1{ B1{ D1, E1 } C1{ F1, G1 } } 
Run Code Online (Sandbox Code Playgroud)

The two threads are sharing the instances of B, D, E, and G.

Now ThreadOne needs to modify object E.

ThreadOne -> A3{ B2{ D1, E2 } C2{ F2, G1 } } 
ThreadTwo -> A1{ B1{ D1, E1 } C1{ F1, G1 } } 
Run Code Online (Sandbox Code Playgroud)

Now ThreadTwo needs the latest version, so ThreadOne just gives it a pointer to its copy.

ThreadOne -> A3{ B2{ D1, E2 } C2{ F2, G1 } } 
ThreadTwo -> A3{ B2{ D1, E2 } C2{ F2, G1 } } 
Run Code Online (Sandbox Code Playgroud)

Since the objects are immutable, there is no danger of any threading issues, and ThreadOne can go right on making changes, each time creating a new instance of only the parts that have changed, and their containers.

ThreadOne -> A4{ B3{ D2, E2 } C2{ F2, G1 } } 
ThreadTwo -> A3{ B2{ D1, E2 } C2{ F2, G1 } } 

ThreadOne -> A5{ B3{ D2, E2 } C3{ F3, G1 } } 
ThreadTwo -> A3{ B2{ D1, E2 } C2{ F2, G1 } } 
Run Code Online (Sandbox Code Playgroud)

This is fast, memory efficient, and thread safe.