2014-03-18 4 views
0

Рассмотрим приведенный ниже фрагмент. В нем я определяю один метод, называемый doit, который впоследствии вызывается из двух разных потоков.Рубиновые потоки: методы и экземпляры объектов

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

Что я ожидал, так это то, что во втором потоке, входящем в метод, он заменит ранее заданный хэш, в результате чего тот же самый идентификатор объекта будет напечатан в остальное время. Другими словами, я думал, что был бы один экземпляр Хэша.

Возможно, это предположило бы, что цикл в первой записи метода заблокировал бы любой последующий доступ к нему, но это, очевидно, не так.

Так что же такое сделка с методами? Каждый вызов из отдельного потока получает свою собственную копию в памяти? Каков правильный способ понять это?

def doit 
    t = Hash.new 
    puts t.object_id 
    loop do 
     sleep 1 
     puts t.object_id 
    end 
end 

t1 = Thread.new { doit } 
t2 = Thread.new { doit } 

t1.join 
t2.join 

В качестве примера, это выход:

21329316 
21327684 
21329316 
21327684 
21329316 
21327684 
21327684 
21329316 
21327684 
21329316 
21327684 
21329316 
+0

Результата, как и следовало ожидать, я думаю, что эти 2 вызовов DoIt имеют свое собственное пространство памяти в стеке. Если вы хотите, чтобы два потока работали на одном объекте, попробуйте передать аргумент методу. как doit (t) – GingerJim

+0

@GingerJim - это не сработает, потому что ссылки параметров скопированы на локальные члены - 't = Hash.new' не изменит' t' в другом вызове функции. –

ответ

2

t является локальная переменная doit, она объявляется только в рамках метода. Каждое исполнение получает его t.

Если вы хотите долиt, объявить его в качестве экземпляра элемента @t:

def doit 
    @t = Hash.new 
    puts @t.object_id 
    loop do 
     sleep 1 
     puts @t.object_id 
    end 
end 

t1 = Thread.new { doit } 
t2 = Thread.new { doit } 

t1.join 
t2.join 

Теперь ваш выход будет выглядеть следующим образом:

15223760 
15223580 
15223580 
15223580 
15223580 
15223580 
15223580 
15223580 
15223580 
15223580 
15223580 
+0

«Частный член» - неправильный термин, «локальная переменная» есть. –

+0

да - избили вас до исправления на 9 секунд ... –

+0

Ах, ваши ответы и Эндрю поставили меня на правильный путь. Конечно, это связано с объемом и не имеет ничего общего с потоками. Хорошо, поэтому каждый вызов находится где-то в памяти, так как, естественно, оба они выполняются одновременно. Когда вы выложите сначала, я приму ваш ответ. Огромное спасибо. – mydoghasworms

1

Threading не имеет ничего общего с ним , t - локальная переменная, инициализированная при каждом вызове doit. Каждый вызов получает свой собственный t. Обратите внимание, что удаление многопоточности дает те же результаты, хотя и не перемежаться:

def doit 
    t = Hash.new 
    t.object_id 
end 

doit #=> 21329316 
doit #=> 21327684 
+0

Спасибо, что делает полный смысл. Сначала ответил Ури, поэтому я приму его ответ, но +1 к вам все равно. Спасибо. – mydoghasworms

Смежные вопросы