2010-08-30 3 views
3

Мой вопрос: почему эта строка - ThreadTest tt = new ThreadTest(); в примере ниже создает общий экземпляр, а не отдельный экземпляр. Пожалуйста, посоветуйте, спасибо!C# создание общего экземпляра

class ThreadTest 
{ 
    bool done; 

    static void Main() 
    { 
    ThreadTest tt = new ThreadTest(); // Create a common instance 
    new Thread (tt.Go).Start(); 
    tt.Go(); 
    } 

    // Note that Go is now an instance method 
    void Go() 
    { 
    if (!done) { done = true; Console.WriteLine ("Done"); } 
    } 
} 

EDIT: Пример от http://www.albahari.com/threading/#_Introduction который демонстрирует, как для обмена данными между потоками.

EDIT2: Мой вопрос, почему именно «экземпляр является общим для обоих потоков»

+0

Что такое 'ThreadTest'? Я не могу найти такой класс в Framework. – Bobby

+0

@Bobby: Ухм, код в вопросе заявляет об этом. – Timwi

+0

@ Тимви: До, я идиот. – Bobby

ответ

4

Неясно, что вы имеете в виду под «общим», например, но конструктор, безусловно, создает новый экземпляр. Метод Go выполняется дважды, один раз в новом потоке и один раз в основном потоке.

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

Внутри метода есть состояние гонки. Он может непредсказуемо печатать «Готово» дважды.

+0

, и ваше предположение верно. Тем не менее, мой вопрос именно в том, почему «экземпляр является общим для обоих потоков». – Stan

+0

Потому что вы создаете только один и используете его дважды. – Timwi

+0

А, я думал, это было как новая тема (tt.Go) .Start(); Go(); – Stan

1

Если вы имеете в виду, что оба звонка на tt.Go делят переменную 'done', то это, конечно же, произойдет. Вы вызываете метод на том же самом объекте, только тот, который происходит в основном потоке, и один происходит в отдельном потоке.

Вы только создаете один экземпляр ThreadTest, но вызываете Go дважды, поэтому оба вызова должны выполняться на одном и том же объекте!

1

6 лет спустя, и я здесь, потому что я читал тот же раздел этой книги. Пример в книге, непосредственно предшествующей той, которую вы упомянули, показывает (статический). Выполняется в анонимном новом потоке, а затем снова отдельно в локальном контексте.

new Thread (Go).Start(); 
Go(); 

Пример ваш вопрос первым создает экземпляр TT, а также изменения .go от того, статический метод к методу экземпляра.

ThreadTest tt = new ThreadTest(); 
new Thread (tt.Go).Start(); 
tt.Go(); 

Так что теперь, когда .go отправляется в новый поток для выполнения, что послана является копия ТТ метода (вместо статического метода .go), который также является то, что запускается на выполнение локально сразу после в строке 3. Поскольку оба исполнения .Go принадлежат tt, они также используют копию tt done. Afaik, поэтому автор называет эти данные «обычными», потому что теперь к ним можно обращаться обоими потоками.

Помимо этого, я по-прежнему шатаюсь по нескольким аспектам пронизывания. Одна загадка для меня - это то, что точно происходит с tt, когда new Thread (tt.Go).Start(); выполняет ... tt был создан в начальной цепочке, но теперь он живет в обоих случаях. Используется ли byref/byval или что-то еще происходит? Точнее ли сказать, что объект tt фактически не «живет» или «принадлежит» ни одному из потоков, а скорее куче, и поэтому оба потока должны иметь к нему доступ?

+2

Собственность объекта скорее логическое различие для программиста, чем техническое. Объект существует (живет) в куче и не имеет «владельца». Он делится, потому что при передаче 'tt.Go' в новый поток он захватывает экземпляр' tt', поэтому новый поток имеет ссылку на 'tt', который обеспечивает его сохранение в живых; основной поток также имеет ссылку на 'tt'. Это, по сути, дает общие данные. Объект живет, пока существует какая-либо ссылка - неважно, какой поток или потоки. – MicroVirus

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