2016-08-25 1 views
0

при написании программы параллелизма, иногда мы используем ссылочный параметр, предположу, что ref1 с поддельным типом Reference, метод какобсуждения параллелизма при использовании эталонного значения

public void testRefVarInMethod(Reference ref1) { 
    Reference ref2 = ref1; 
    .... 
    .... 
} 

В этом методе, я объявляю новую переменный ref2, который указывает на ref1. Мы все знаем, что переменная метода является потокобезопасной, однако, что касается ссылки ref1, любой может изменить ее значение вне метода, поэтому значение ref2 будет изменено. Я думаю, это не может гарантировать потокобезопасность, почему некоторые люди пишут такой код?

ответ

0

Именно поэтому люди используют методы, такие как clone для обеспечения безопасности потоков.

Reference ref2 = ref1.clone(); 

Обращаясь к копии ref1, ref2 не будет затронут независимо от того, как ref1 изменен некоторыми другими потоками.

Edit: Как было отмечено в комментариях, метод clone не обязательно обеспечивать безопасность потоков. Он должен быть правильно реализован таким образом, что изменение ref1 не изменит состояние ref2. то есть ref1 и ref2 не делятся никакими изменяемыми полями.

+0

Существует много потенциальных проблем с 'clone()', и неверно предполагать, что все его использование приведет к правильным программам. Я не проголосовавший. – scottb

+0

@scottb Да, я согласен, метод 'clone' должен быть правильно реализован. Ответ обновлен. – onsankawai

0

Значение локальной переменной ref2 само по себе не может быть изменено вне вашего метода (никто не может указывать на другой объект извне). Это только состояние объекта, на котором он ссылается, который можно изменить (кто-то может позвонить ref1.setField(newValue)) одновременно.

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

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

synchronized(ref2) { 
    // Change or read object here 
} 

Если весь код использует тот же подход, что делает изменения (и их чтение) на объекте будут в безопасности.

Там уже много других, более специализированных и более эффективно, примитивы синхронизации и методы, которые вы должны узнать о том, если вы собираетесь писать многопоточные программы с общими объектами: неизменность, volatile, ReadWriteLock и т.д. Такие книги, как «Java Параллелизм на практике "может дать вам хорошее введение в поле.

+0

Спасибо, я закончил читать отличную книгу «Java Concurrency in Practice» – lawrence

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