Ruby on rails Rails线程测试db锁

Ruby on rails Rails线程测试db锁,ruby-on-rails,ruby,multithreading,Ruby On Rails,Ruby,Multithreading,假设我们要测试数据库是否被锁定 $transaction = Thread.new { Rails.logger.debug 'transaction process start' Inventory.transaction do inventory.lock! Thread.stop inventory.units_available=99 inventory.save end } $race_condition

假设我们要测试数据库是否被锁定

$transaction = Thread.new  {
    Rails.logger.debug 'transaction process start'
    Inventory.transaction do
      inventory.lock!
      Thread.stop
      inventory.units_available=99
      inventory.save
    end
  }
  $race_condition = Thread.new  {
    Rails.logger.debug 'race_condition process start'
    config = ActiveRecord::Base.configurations[Rails.env].symbolize_keys
    config[:flags] = 65536 | 131072 | Mysql2::Client::FOUND_ROWS
    begin
      connection = Mysql2::Client.new(config)

      $transaction.run
      $transaction.join
    rescue NoMethodError
    ensure
      connection.close if connection
    end
  }
  Rails.logger.debug 'main process start'
  $transaction.join
  Rails.logger.debug 'main process after transaction.join'
  sleep 0.1 while $transaction.status!='sleep' 
  Rails.logger.debug 'main process after sleep'
  $race_condition.join
  Rails.logger.debug 'main process after race_condition.join'
理论上,我认为它将执行事务线程,然后等待(thread.stop),然后主进程将看到它正在休眠,并启动竞争条件线程(当它实际工作时,它将尝试更改锁定表中的数据)。然后,竞争条件将在完成后继续事务线程

奇怪的是痕迹

main process start
transaction process start
race_condition process start
从nodejs来看,线程似乎并不完全是用户友好的。。不过,必须有办法做到这一点


是否有一种更简单的方法来锁定数据库,然后尝试使用不同的线程对其进行更改?

对于任何要使其成为“互斥”的资源,您需要使用互斥对象类,并使用同步方法在一个线程使用资源时将其锁定。你必须这样做:

semaphore=Mutex.new

并在线程实例中使用它

$transaction = Thread.new  { 
  semaphore.synchronize{
  # Do whatever you want with the *your shared resource*
  }
}
这样可以防止任何死锁


希望这有帮助

Thread.new自动启动线程。 但这并不意味着它正在执行。 这取决于操作系统、ruby或jruby、内核数量等

在您的示例中,主线程运行到 $transaction.join, 只有到那时,您的事务线程才会启动,只是碰巧而已。 它仍然运行Thread.stop,然后您的“$race\u condition”线程启动,因为其他两个线程都被阻塞(它可能以前启动过)

这就解释了你的日志

您有两个$transaction。加入
他们一直等到线程退出,但是一个线程只能退出一次。。。 我不知道接下来会发生什么,也许第二个电话会一直等下去

对于您的测试,需要某种类型的显式同步,以便当事务处理线程位于事务中间时,我们的RraceX线程精确写入。您可以使用互斥来实现这一点,但最好是某种消息传递。以下博客文章可能会有所帮助:


查看我的答案,如果有帮助,请打分!干杯:)