软件事务内存 - 可组合性示例 [英] Software Transactional Memory - Composability Example

查看:155
本文介绍了软件事务内存 - 可组合性示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

软件事务内存的一个主要优点是可组合性和模块化。可以组合不同的片段以产生更大的组分。在基于锁的程序中,通常不是这样。



我正在寻找一个简单的例子,用实际代码来说明这一点。我喜欢在Clojure中的一个例子,但Haskell也很好。

解决方案

一个例子,当锁被禁止时用Java编写:

  class Account {
float balance;
synchronized void deposit(float amt){
balance + = amt;
}
同步void withdraw(float amt){
if(balance< amt)
throw new OutOfMoneyError();
balance - = amt;
}
synchronized void transfer(Account other,float amt){
other.withdraw(amt);
this.deposit(amt);
}
}

因此,存款是好的,转移不正常:如果A开始转移到B,当B开始转移到A,我们可能有一个死锁情况。



现在在Haskell STM:

  withdraw :: TVar Int  - > Int  - > STM()
撤销acc n = do bal< - readTVar acc
如果bal<然后重试
writeTVar acc(bal-n)

deposit :: TVar Int - > Int - > STM()
deposit acc n = do bal< - readTVar acc
writeTVar acc(bal + n)

deposit :: TVar Int-> TVar Int - > Int - > STM()
从到n的转移从n
存款转到n

由于没有明确的锁, withdraw deposit code>。语义仍然确保如果提取失败,则整个传输失败。它还确保退出和存款将原子性地完成,因为类型系统确保您不能在原子之外调用转移。

  atomically :: STM a  - > IO a 

此示例来自于:
http://cseweb.ucsd.edu/classes/wi11/cse230/static/lec-stm-2x2.pdf
改编自本文,你可能想读:
http:// research。 microsoft.com/pubs/74063/beautiful.pdf


One of the major advantages of software transactional memory that always gets mentioned is composability and modularity. Different fragments can be combined to produce larger components. In lock-based programs, this is often not the case.

I am looking for a simple example illustrating this with actual code. I'd prefer an example in Clojure, but Haskell is fine too. Bonus points if the example also exhibits some lock-based code which can't be composed easily.

解决方案

An example where locks don't compose in Java:

class Account{
  float balance;
  synchronized void deposit(float amt){
    balance += amt;
  }
  synchronized void withdraw(float amt){
    if(balance < amt)
      throw new OutOfMoneyError();
    balance -= amt;
  }
  synchronized void transfer(Account other, float amt){
    other.withdraw(amt);
    this.deposit(amt);
  }
}

So, deposit is okay, withdraw is okay, but transfer is not okay: if A begins a transfer to B when B begins a transfer to A, we can have a deadlock situation.

Now in Haskell STM:

withdraw :: TVar Int -> Int -> STM ()
withdraw acc n = do bal <- readTVar acc
                    if bal < n then retry
                    writeTVar acc (bal-n)

deposit :: TVar Int -> Int -> STM ()
deposit acc n = do bal <- readTVar acc
                   writeTVar acc (bal+n)

deposit :: TVar Int -> TVar Int -> Int -> STM ()
transfer from to n = do withdraw from n
                        deposit to n

Since there is no explicit lock, withdraw and deposit compose naturally in transfer. The semantics still ensure that if withdraw fails, the whole transfer fails. It also ensures that the withdraw and the deposit will be done atomically, since the type system ensures that you cannot call transfer outside of an atomically.

atomically :: STM a -> IO a

This example comes from this: http://cseweb.ucsd.edu/classes/wi11/cse230/static/lec-stm-2x2.pdf Adapted from this paper you might want to read: http://research.microsoft.com/pubs/74063/beautiful.pdf

这篇关于软件事务内存 - 可组合性示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆