Ruby中是否有保证/记录为原子的操作/方法?

Ruby中是否有保证/记录为原子的操作/方法?,ruby,concurrency,Ruby,Concurrency,我在谷歌上快速搜索了一下,几乎所有用Ruby编写的关于atomicity的东西都建议在操作周围包装一个互斥体。然而,我怀疑这种方法不满足原子性的通常定义,因为信号可能会中断同步代码。例如(摘自): 我知道原子性对于高级语言来说不太重要,但为了研究起见,我想得到一个关于使用GIL(例如MRI 2.0.0)和不使用JRuby 1.7.4和Rubinius 1.2.4的实现的规范答案。我对这个主题的知识非常有限。但我会尽力回答 Jesse Storimer写了一篇关于并发的非常好的文章。我强烈建议你阅

我在谷歌上快速搜索了一下,几乎所有用Ruby编写的关于atomicity的东西都建议在操作周围包装一个互斥体。然而,我怀疑这种方法不满足原子性的通常定义,因为信号可能会中断同步代码。例如(摘自):


我知道原子性对于高级语言来说不太重要,但为了研究起见,我想得到一个关于使用GIL(例如MRI 2.0.0)和不使用JRuby 1.7.4和Rubinius 1.2.4的实现的规范答案。我对这个主题的知识非常有限。但我会尽力回答

Jesse Storimer写了一篇关于并发的非常好的文章。我强烈建议你阅读所有关于它的三个部分

第2部分的结论是GIL保证原生C方法实现是原子的

你给出的例子实际上更多的是重入问题,而不是原子性。我不知道这是否是同一件事,也不知道它之间的关系有多密切

正如本文所解释的,ruby不同于事件驱动编程,在事件驱动编程中回调是同步的,这意味着如果您发送两次信号USR1,第二个处理程序将在第一个处理程序完成后执行。因此,您不会两次锁定互斥锁

但是在ruby中,信号处理是异步的。意思是如果你发送两次信号。第二个处理程序将中断第一个处理程序。因为第一个处理程序已经获取了锁,那么尝试获取相同锁的第二个处理程序将抛出异常。我相信这个问题不是ruby特有的

解决这个问题的方法之一是创建一个队列来进行信号处理。另一个解决方案是使用一种称为“自我管道”的方法。这两种方法都适用。在这篇文章中,令人敬畏的Jesse Storimer再次解释了这一点:

所以, 对于MRI 2.0.0,我相信仍然有GIL,所以ruby只保证原生C方法是原子的

JRuby是JVM支持的,所以我猜所有的线程和锁定机制都是在JVM之上实现的

Rubinius 1.2还有GIL,所以我相信它和MRI一样。但是Rubinius 2.x移除了GIL。我对鲁宾尼乌斯没有太多的经验,所以我不能完全肯定


为了回答这个问题,如果您使用ruby中的多线程应用程序。互斥体类应该保护块一次只能由单个线程执行。

我对这个主题的了解非常有限。但我会尽力回答

Jesse Storimer写了一篇关于并发的非常好的文章。我强烈建议你阅读所有关于它的三个部分

第2部分的结论是GIL保证原生C方法实现是原子的

你给出的例子实际上更多的是重入问题,而不是原子性。我不知道这是否是同一件事,也不知道它之间的关系有多密切

正如本文所解释的,ruby不同于事件驱动编程,在事件驱动编程中回调是同步的,这意味着如果您发送两次信号USR1,第二个处理程序将在第一个处理程序完成后执行。因此,您不会两次锁定互斥锁

但是在ruby中,信号处理是异步的。意思是如果你发送两次信号。第二个处理程序将中断第一个处理程序。因为第一个处理程序已经获取了锁,那么尝试获取相同锁的第二个处理程序将抛出异常。我相信这个问题不是ruby特有的

解决这个问题的方法之一是创建一个队列来进行信号处理。另一个解决方案是使用一种称为“自我管道”的方法。这两种方法都适用。在这篇文章中,令人敬畏的Jesse Storimer再次解释了这一点:

所以, 对于MRI 2.0.0,我相信仍然有GIL,所以ruby只保证原生C方法是原子的

JRuby是JVM支持的,所以我猜所有的线程和锁定机制都是在JVM之上实现的

Rubinius 1.2还有GIL,所以我相信它和MRI一样。但是Rubinius 2.x移除了GIL。我对鲁宾尼乌斯没有太多的经验,所以我不能完全肯定


为了回答这个问题,如果您使用ruby中的多线程应用程序。互斥类应该保护块一次只能由单个线程执行。

什么Ruby引擎和版本?Ruby:MRI中的原子操作与JRuby&Rubinius中的原子操作非常不同,因为有。什么Ruby引擎和版本?Ruby:MRI中的原子操作与JRuby&Rubinius中的原子操作非常不同,因为。
lock = Mutex.new

# XXX this is an example of what NOT to do inside a signal handler:
trap(:USR1) do
  lock.synchronize do
    # if a second SIGUSR1 arrives here, this block of code
    # will fire again.   Attempting Mutex#synchronize twice
    # the same thread leads to a deadlock error
  end
end