Как запустить два потока в Ruby одновременно? - PullRequest
3 голосов
/ 11 марта 2010

Есть ли способ запустить 2 потока одновременно?

Я хочу, чтобы мое приложение запустило свою текущую функцию, а затем вызвало другой поток, выполняющий другую функцию, которая может изменять переменные в первом потоке.

Ответы [ 4 ]

15 голосов
/ 12 марта 2010

Если вы хотите запустить два потока одновременно, весь стек выполнения должен быть в состоянии это сделать. Начнем с вершины:

  1. Сам Ruby способен запускать два потока одновременно, никаких проблем нет. Однако Ruby - это просто язык программирования, то есть просто набор правил. Чтобы запустить вашу программу, вам нужна реализация Ruby . К сожалению, многие популярные реализации Ruby не способны запускать несколько потоков одновременно, включая MRI, YARV и Rubinius. Фактически, только готовая к реализации реализация Ruby, которая может одновременно запускать потоки, является JRuby. (IronRuby тоже, но технически он еще не готов к работе, хотя до окончательной версии 1.0, вероятно, осталось всего несколько дней.)
  2. Но JRuby (и IronRuby) на самом деле не реализуют сами потоки, они просто используют потоки базовой платформы. То есть JRuby отображает потоки Ruby в потоки JVM, а IronRuby отображает их в потоки CLI. Таким образом, базовая платформа должна иметь возможность запускать потоки параллельно.
  3. Опять же: и JVM, и CLI в принципе способны запускать потоки параллельно, но JVM и CLI - это просто спецификации, они просто кусочки бумаги. Для запуска вашего кода вам нужна реализация этих спецификаций, и не все из них do поддерживают действительно параллельные потоки.
  4. Даже , если ваша платформа поддерживает действительно параллельные потоки, они могут сами делегировать свою реализацию потоков в базовую ОС, точно так же, как JRuby делегирует JVM. Например, .NET, Mono, HotSpot и JRockit (которые являются наиболее популярными реализациями CLI и JVM соответственно) используют собственные потоки ОС для своих потоков платформы. Таким образом, очевидно, что ОС должна иметь возможность запускать потоки параллельно. И снова: не все из них.
  5. И, конечно, весь параллелизм в ОС не помогает, если у вас только один процессор. Если вы хотите, чтобы два потока работали одновременно, вам понадобятся либо два процессора, два ядра или два одновременных аппаратных потока.
2 голосов
/ 11 марта 2010

http://ruby -doc.org / ядро ​​/ классы / Thread.html

x = 2
Thread.new do
    x = 3
end
x = 4

Для истинного параллелизма требуется более 2 ядер или 2 процессора, но он может не работать, если реализация однопоточная (например, MRI).

1 голос
/ 12 марта 2010

Сначала я отвечу на ваш вопрос:

thread_1 = Thread.new do
    #do something here
end

thread_2 = Thread.new do
   #do something here
end

thread_1.join
thread_2.join(timeout_in_seconds)

Thread#join заставляет главный поток ждать, пока не завершится присоединенный поток. Если вы укажете тайм-аут в секундах, Ruby закроет поток после того, как истечет этот тайм-аут.

Теперь, по правде говоря, в Ruby 1.8 нет реального параллелизма с интерпретатором Matz Ruby Interpreter (MRI) и нет реального параллелизма только с одним процессором. Согласно этой странице :

Однако, как часть этой среды выполнения, интерпретатор также создает экземпляр Global Interpreter Lock (или более нежно известного как GIL), который является причиной нашего отсутствия параллелизма

Прочтите саму статью для получения дополнительной информации.

МРТ пытается обмануть вас, используя то, что называется Зеленые потоки , что означает, что интерпретатор Ruby позаботится обо всем, что связано с потоками, а не с ОС, другими видами потоков, которые действительно параллельны называются собственными потоками, и Ruby 1.9 поддерживает их через YARV, но это не означает, что каждый поток Ruby работает параллельно, потому что YARV имеет глобальную блокировку виртуальной машины (глобальную блокировку интерпретатора или GIL), поэтому параллелизм - это миф в ruby, и он долгое время.

0 голосов
/ 11 марта 2010

http://ruby -doc.org / ядро ​​/ классы / Thread.html
Помните, что только в потоках JRuby действительно параллельные (другие интерпретаторы реализуют GIL ). С здесь :

# mutexsyncex.rb  
require 'thread'  # For Mutex class in Ruby 1.8  

# A BankAccount has a name, a checking amount, and a savings amount  
class BankAccount  
  def initialize(name, checking, savings)  
    @name,@checking,@savings = name,checking,savings  
    @lock = Mutex.new  # For thread safety  
  end  

  # Lock account and transfer money from savings to checking  
  def transfer_from_savings(x)  
    @lock.synchronize {  
      @savings -= x  
      @checking += x  
    }  
  end  

  # Lock account and report current balances  
  def report  
    @lock.synchronize {  
      "#@name\nChecking: #@checking\nSavings: #@savings"  
    }  
  end  
end 

ba = BankAccount.new('me', 1, 400)

ba.transfer_from_savings(10);
puts ba.report
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...