Concurrency 使用参与者建模同步

Concurrency 使用参与者建模同步,concurrency,actor,Concurrency,Actor,我试图理解如何使用演员解决问题。如果您不知道,问题的关键是一个线程需要获得两个锁才能继续…并且有多个线程在争夺这两个锁 这里有一种方法,我可以使用actors对其进行建模: # asynchronously request locks from 2 forks (both forks are actors) lock1 = fork1.future.lock lock2 = fork2.future.lock if lock1 && lock2 # wait to get bo

我试图理解如何使用演员解决问题。如果您不知道,问题的关键是一个线程需要获得两个锁才能继续…并且有多个线程在争夺这两个锁

这里有一种方法,我可以使用actors对其进行建模:

# asynchronously request locks from 2 forks (both forks are actors)
lock1 = fork1.future.lock
lock2 = fork2.future.lock

if lock1 && lock2 # wait to get both locks
  ... critical section
end
但我认为,如果两个线程各有一个锁,并等待另一个线程放弃其锁,则会导致死锁


一般来说,如何使用actors对访问两个资源进行原子建模?

使用actors在Scala中编写了一个很好的解决方案。

actors的思想是没有任何锁,以免由于不正确的同步而陷入死锁或其他问题。因此,将锁与演员结合使用会让你重新回到演员想要解决的问题。问题是,存在着对免费分叉的争夺,因此共享数据。当没有任何共享数据时,参与者工作得非常好。例如,您可以使用java.util.concurrent.ConcurrentHashMap共享简单的共享数据,这是一种无锁且足以解决此类问题的方法

现在ConcurrentHashMap不会发送事件,以防某些哲学家放下叉子。我曾经实现了一个简单的ConcurrentMap,让您可以注册事件,请参阅。看看它是如何使用的。要运行此代码需要JDK8,您可以从下载


这个ConcurrentEventMap更像是一个暂时的混乱。我正在努力使用ScalaSTM获得更好的实现(请参阅)。这可能也是您的一个选择。

这看起来是正确的,但如果筷子是互斥体而不是参与者,代码将是相同的:1。锁定
左侧
互斥锁。2.尝试锁定
右侧
互斥锁。如果你成功了,吃吧!否则,请解锁左互斥锁并重试。所以我可以说演员在这里没有提供任何特别的东西吗?通过这种方式对问题进行建模,并使用筷子和食客的状态,就不会涉及到互斥不能实现的阻塞操作。这个设计在博客文章中有解释。不过你也可以避免使用互斥锁进行阻塞。例如,Ruby的互斥锁有
lock
try\u lock
lock
阻塞,但
try\u lock
不阻塞,您只需稍后再试。使用
Concurrency::join
等待多条消息。听起来这是演员的延伸。好吧,我终于在一些帮助下弄明白了。我没有正确地建模状态。这里有一个正确的解决方案,使用服务员:这也正是我所想的。事实证明,我没有使用参与者正确地建模共享状态。看看我的解决方案。另请参见赛璐珞邮件列表。我喜欢STM,我想比较演员和STM在这个问题上的表现,所以这个问题。演员和STM很好地结合在一起。如果你看Akka,你会发现他们也使用ScalaSTM。STM基于某种乐观锁定。因此,当读者比作家多的时候,演员和STM会很好地发挥作用。如果编写器的数量很高,您就达到了STM的限制,以防您无法通过更改概念/设计来降低编写器的数量。