Tag: stm

并发通用数据结构,没有死锁或资源匮乏

我最近问了一些有关TVar的问题,我仍然对livelock感到担忧。 所以我想到了这个结构: 每个事务都有一个唯一的优先级(可能是按创build顺序分配的)。 事务尝试获取对其访问的数据的读/写locking。 自然地,同时读取是可以的,但是一个写入locking排除所有其他(读取和写入)。 说事务A的优先级比事务B的优先级高。如果A持有锁,B等待,但是如果B持有锁并且A需要它,则B从锁中引导,A获得它,并且事务B重新启动(如同TVar ) 。 然而B保持当前优先重试。 当一个锁被释放并且等待事务时,它将进入最高优先级的事务,其余的继续等待。 我相信这个系统可以防止死锁,但也可以防止饥饿(与TVar不同)。 我想知道是否有人实施了这样一个系统,因为它似乎相当明显,我不想重新发明轮子。 当然,这样的方法很容易扩展到允许用户指定优先级。 优先级可以是pair (user_supplied_prio, auto_increment) , user_supplied_prio优先,但优先级相同的任务按FIFO顺序parsing。 评论/解决scheme: 实际上,当我想到这一点时,Haskell中已经存在,只需要使用一个IORef包装所有的数据,并且只使用atomicModifyIORef 。 atomicModifyIORef将确保交易按顺序应用。 但是,有人可能会认为这意味着数据结构是顺序的(即有效地限于一个线程),但实际上由于懒惰而是并行的。 为了解释这一点,考虑一个昂贵的函数f 。 我们打算把这个应用到一个Data.Map的关键字“foo”的数据。 用(foo -> future(fx))replace(foo -> x) (foo -> future(fx)) 。 这个线程将继续确定(fx)实际是什么,但同时我们可以将g应用到“bar”中。 由于将g应用于“bar”并不需要“foo”的结果,因此我们可以同时处理这个问题。 没有死锁,没有饥饿,最终所有交易将被处理(大致按照他们收到的顺序)。

TVar和TMVar的区别

我已经看到了TVar是一个简单的容器,而TMVar和MVar是一样的,意思是它有一个锁等,但是在STM monad中。 我想知道为什么这是必要的,因为STM的想法是不需要锁。 那么,如果你有一个像[Handle]types的套接字句柄的列表,你希望在forkIO之间使用哪个线程呢?