Erlang ETS 原子和隔离

Posted

技术标签:

【中文标题】Erlang ETS 原子和隔离【英文标题】:Erlang ETS atomic and isolated 【发布时间】:2017-03-01 07:59:53 【问题描述】:

来自ets doc,保证对单个对象的所有更新都是原子的和隔离的。这意味着对单个对象的更新操作要么成功,要么完全失败,没有任何影响(原子性),并且其他进程看不到更新的中间结果(隔离)。

对于下面的代码,我将两个表打包成一个

我的问题:

    这是 Erlang 中的常见模式吗?

    对于插入和更新,是原子的还是隔离的?

    -模块(example_store)。 -出口([初始化/0, 插入/1, 更新/1])。

    init() -> ets:新(商店,[公共, 命名表, read_concurrency, true, write_concurrency, true]),

    数据 = ets:new(store_data, [public, 命名表, read_concurrency, true, write_concurrency, true]),

    Info = ets:new(store_info, [public,ordered_set,
            named_table,
              read_concurrency, true,
        write_concurrency, true]),
    
     ets:insert(store, store, Data, Info).
    
    
    %% insert data
    insert(Key, Value, Info) ->
       store, Data_tb, Info_tb = ets:lookup(store, store),
        ets:insert(Data_tb, Key, Value),
        ets:insert(Info_tb, Info, Key),
        ok.
    
    
    %% update data
    update(Key, Value, Info, Info_old) ->
         store, Data_tb, Info_tb = ets:lookup(store, store),
         ets:insert(Data_tb, Key, Value),
         ets:delete(Info_tb, Info_old,Key),
         ets:insert(Info_tb, Info, Key),
         ok.   
    

Update_1 来自@Derek Brown,包裹表不能保证insert/1update/1 被隔离。

Q3 : 是否可以将其隔离? (除了 Gen_server)

【问题讨论】:

【参考方案1】:

1) 否。当您使用 named_table 时,从 ets:new/2 返回的名称与您用于第一个参数的名称相同。这就是您在store 表中存储的内容——名称。所以在insert/1update/1 中你也可以直接使用store_datastore_info 原子。

2) 不,插入和更新既不是原子的,也不是孤立的。不是原子的,因为这不是函数在 Erlang 中的工作方式。例如,如果您的insert/1 中的第一个ets:insert/2 调用成功,但第二个由于某种原因失败,则第一个不会自动回滚。并且不是孤立的,因为不能保证给定的函数(例如,insert/1update/1)将以原子方式执行。在您的功能完成之前,其他进程可能会看到中间效果。

【讨论】:

除了gen_server,有没有办法保证update被隔离?

以上是关于Erlang ETS 原子和隔离的主要内容,如果未能解决你的问题,请参考以下文章

Erlang - ETS 表之间的比较

Erlang ETS Table

Erlang ets插入多个表

有没有办法浏览 erlang 术语存储 (ETS)

为啥 Erlang 字符串不能用作 ets 表名?

Erlang ETS 内存碎片