Передать ссылку на объект в новый поток

У меня есть объект, который содержит очень большой 3D-массив двойников, и мне нужно запустить новый поток, которому нужны данные этого массива, поэтому мне нужно либо запустить новый поток, передавая объект (который содержит много другие данные тоже) в новый поток, или я просто передаю 3D-массив в новый поток. Для первого решения я бы просто сделал следующее:

MyClass
{
    ...
    public double[,,] _data = new double[x,y,z];
    ...
}

MyMethod(object MyObject)
{
    //do stuff with (MyObject as MyClass)
}

MyClass _newObject = new MyClass();

Thread thread = new Thread(new ParameterizedThreadStart(MyMethod));
thread.Start(_newObject);

Теперь мой вопрос: когда я передаю объект _newObject в новый поток, этот объект отправляется в поток по ссылке или объект копируется, а копия используется новым потоком? Проблема в том, что объект содержит данные размером около 300 МБ, и было бы почти невозможно, если бы использовались копии, поскольку мне нужно запустить около 10 потоков, которые должны использовать данные этого объекта.


person philkark    schedule 06.09.2012    source источник
comment
Ну, я прочитал две толстые книги о C# и поискал в Интернете, но ничего не нашел. Я не просто задаю вопросы, не пытаясь сначала выяснить это самостоятельно. Книги не освещали ParameterizedThreadStart достаточно хорошо, чтобы объяснить, как передаются данные.   -  person philkark    schedule 06.09.2012


Ответы (4)


По ссылке.

Если вы измените данные в своем потоке, это изменит исходные данные, которые вы ввели. То же самое применимо, если вы измените данные вне потока, ваш поток увидит измененные данные.

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

person BlueM    schedule 06.09.2012
comment
Думаю, я буду читать о механизмах блокировки. Это будет иметь больше смысла, чем запускать потоки один за другим вместо этого... - person philkark; 06.09.2012
comment
Нужен ли мне механизм блокировки, если я просто читаю данные? Метод потока никогда не изменит данные, а только проведет с ними вычисления. - person philkark; 06.09.2012
comment
Вам нужна блокировка, если вы одновременно меняете данные где-то. Если вы ТОЛЬКО читаете данные и никогда не меняете их одновременно, вам не нужна блокировка. - person BlueM; 06.09.2012
comment
Спасибо, это очень важно для меня. Я буду только читать данные. - person philkark; 06.09.2012

10 нить? как вы планируете поддерживать целостность данных _newObject ? Сказав, что копии не будут переданы, будет использована только ссылка. Если вы собираетесь вызывать метод MyMethod(object MyObject) в 10 разных потоках, MyObject будет разными объектами?? если нет, вам лучше преломить метод.

Также вы должны помнить, что поток — это просто линейный набор инструкций, которые необходимо выполнить. Таким образом, только из-за использования нескольких потоков размер вашего объекта не будет увеличиваться в памяти.
Само преимущество многопоточности заключается в использовании разных потоков для обработки ваших инструкций, а не в копировании объектов.

person Vignesh.N    schedule 06.09.2012
comment
Нет, это один и тот же объект. Мне нужно сделать много вычислений одновременно, но по-другому. Думаю, я могу изменить код так, чтобы вычисления выполнялись один за другим, так что одновременно выполнялся только один поток. - person philkark; 06.09.2012
comment
опять же, когда один поток ждет, пока предыдущий поток будет работать с тем же объектом, тогда какой смысл в многопоточности?? - person Vignesh.N; 06.09.2012
comment
Это был мой вопрос. В конце концов, если вы передаете данные методу, эти данные копируются, я думал, что если я передам объект новому потоку, данные также могут быть скопированы. - person philkark; 06.09.2012
comment
Никакие данные не будут скопированы, они будут переданы как ссылка по умолчанию, и вам также необходимо сделать метод потокобезопасным. И с образцом, который вы опубликовали, я не вижу никакого преимущества, потому что эти 10 потоков все равно должны выполняться один за другим. Если, конечно, вы не выполняете какую-то другую операцию в основном потоке, ожидая завершения этих потоков. - person Vignesh.N; 06.09.2012

Предполагая, что ваш MyClass является классом, тогда ссылка на объект передается только новому потоку, поскольку это ссылочный тип (узнайте больше о ссылочных типах в MSDN), я бы также посоветовал вам использовать блокировку, чтобы избежать взаимоблокировок, вы можете сделать это, просто используя lock ключевое слово

person Vamsi    schedule 06.09.2012
comment
Согласно BlueM, мне не нужно блокировать данные, так как я получаю доступ к данным, только читая их, чтобы выполнять с ними вычисления и никогда не меняю их в потоке. - person philkark; 06.09.2012
comment
да, это правильно, если вы не изменяете объект одновременно в любом потоке, включая поток пользовательского интерфейса, в случае, если вы его меняете, вам нужно получить блокировку, прежде чем делать это - person Vamsi; 06.09.2012

Чтобы быть более точным, он отправляется в виде референсной копии.

Поскольку это reference type, в этом случае копируется только ссылка, а не все данные.

Вот почему вы должны заботиться о locking mechanisms в тех случаях, когда более одного thread обращается к данным, на которые ссылается этот объект.

person Tigran    schedule 06.09.2012
comment
Спасибо за ответ. Однако я не уверен, понимаю ли я, что именно вы имеете в виду, возможно, небольшой пример кода поможет мне понять... - person philkark; 06.09.2012
comment
Я имею в виду то, что вы копируете 4-байтный (для 32-битных машин) указатель, и никак иначе. Не беспокойтесь о 300 МБ. - person Tigran; 06.09.2012
comment
Хорошо, спасибо, теперь мне нужно изучить механизмы блокировки, если я получу доступ к данным. Как я сказал BlueM, я никогда не буду изменять данные объекта, только использовать их для вычислений, нужно ли мне тогда заботиться о его блокировке? - person philkark; 06.09.2012
comment
@ phil13131: если речь идет только о чтении статических значений (с точки зрения значений, скажем, просто набора чисел), и никаких расчетов, доступа к файловой системе или любых других вещей не происходит во время доступа к эту информацию, вы можете не беспокоиться о блокировке. - person Tigran; 06.09.2012
comment
Да, спасибо, я пытался узнать об этой теме около часа, но не смог найти четкого ответа, даже ни в одной из моих книг. Я не понимаю, почему я проголосовал за этот вопрос. - person philkark; 06.09.2012