Здравствуйте, Lloyd, Вы писали:
L>lock (_lock) {
На всякий уточню для топикстартера: код во всех остальных потоках тоже должен использовать lock для обращений к общему ресурсу (методам, объекту — неважно).
И, такие вопросы возникают внезапно, лучше пересмотреть подход к задаче.
Re[3]: Непередача управления другому потоку
От:
Аноним
Дата:
24.02.11 16:11
Оценка:
Здравствуйте, Sinix, Вы писали:
Здравствуйте, Lloyd, Вы писали:
спасибо всем
L>>lock (_lock) { S>На всякий уточню для топикстартера: код во всех остальных потоках тоже должен использовать lock для обращений к общему ресурсу (методам, объекту — неважно).
почему? можно пример, пожалуйста
S>И, такие вопросы возникают внезапно, лучше пересмотреть подход к задаче.
почему?
Здравствуйте, Аноним, Вы писали:
L>>>lock (_lock) { S>>На всякий уточню для топикстартера: код во всех остальных потоках тоже должен использовать lock для обращений к общему ресурсу (методам, объекту — неважно). А>почему? можно пример, пожалуйста
Потому что рантайм ничего не знает о содержимом блока lock. lock(someLockKey) гарантирует, что любой другой поток не сможет поставить блокировку на someLockKey, пока исходный поток не освободит его.
Если упростить ещё сильнее, то запущенный в несколько потоков код lock(lockKey) { somecode } гарантирует, что somecode не будет выполняться одновременно в нескольких потоках. Но _не_ гарантирует, что потоки будут получать блокировку по какому-нибудь предсказуемому порядку. И _не_ гарантирует, что поток без lock(lockKey) не может выполнить somecode.
Возвращаясь к исходному вопросу: без блокировки другой поток вызовет f1/f2/f3 или ещё как-то повлияет на разделяемое состояние, и это будет полнейшим сюрпризом для исходного потока.
S>>И, такие вопросы возникают внезапно, лучше пересмотреть подход к задаче. А>почему?
Потому что многопоточность очень сложная и обширная тема; надо думать по-другому, писать код по-другому, даже банальная отладка приносит кучу проблем. И, увы, очень мало алгоритмов дают хоть какой-то выхлоп от параллельности.
Главная загвоздка — в непредсказуемости порядка выполнения кода. Две строчки в разных потоках могут выполняться в произвольном порядке, физически одновременно (на разных ядрах процессора) или вперемешку — для неатомарных инструкций и в особенности для систем со слабой моделью памяти. Больше строчек, больше потоков — больше комбинаций, меньше надёжного, предсказуемого кода.
Разумеется, если два потока никак не влияют друг на друга — не используют одни и те же поля, ref-переменные, файлы, потоки, системные настройки и т.д. и т.п. — никаких проблем нет. Только такого кода практически не бывает. Обычно с параллельностью возятся по 2м причинам:
1. Наш код тормозит, а процессор простаивает.
2. Мы услышали, что параллельность — это круто.
В любом из вариантов исходный код будет весь нашпигован изменением состояния. Для однопоточного кода это не страшно — какая разница, раз вы запихнули в x строчку "hello world", она там и останется, так? Для многопоточного — не так. И вот чтобы победить это маленькое "не так", не превращая весь код обратно в однопоточный, наворочено столько, что самому страшно. Короче говоря, не надо туда лезть без особой необходимости, изучения матчасти и ясного понимания того, что делаешь
Здравствуйте, Sinix, Вы писали:
S>Разумеется, если два потока никак не влияют друг на друга — не используют одни и те же поля, ref-переменные, файлы, потоки, системные настройки и т.д. и т.п. — никаких проблем нет. Только такого кода практически не бывает.
Бывает.
>Обычно с параллельностью возятся по 2м причинам: S>1. Наш код тормозит, а процессор простаивает.
Вот поэтому и бывает. Разделение задачи на подзадачи не обязательно требует доступа к общим данным.
With best regards
Pavel Dvorkin
Re: Непередача управления другому потоку
От:
Аноним
Дата:
27.02.11 21:11
Оценка:
Здравствуйте, Аноним, Вы писали:
А>У меня есть вызовы функция которая делает несколько вызовов: А>Что нужно сделать чтобы во время выполнения f() передача другому поктоку не произошла? Надо чтобы f() была выполнена как одно целое .
Я сейчас проверил решение с lock:
private readonly object _lock = new object();
public void f()
{
lock (_lock) {
f1();
f2();
f3();
}
А>}
А>
Вроде как основной поток стал работать в время исполнения f2. Мне надо чтобы второй поток мог начать работать только после того как f() закончила работу.
Т.е. надо как-то приостановить все потоки, кроме того, который в данный момент исполняет f(), а после f() снова все запустить.
> Что нужно сделать чтобы во время выполнения f() передача другому поктоку не произошла? Надо чтобы f() была выполнена как одно целое.
Нужно что бы остальные потоки ждали разрешения на продолжение работы, а разрешение даст выход из функции f1.
При этом возникнут различные ньюансы, но для начала о них можно забыть.
Ну, и я надеюсь что "передача другому контролируемому мной потоку не произошла".
>Надо чтобы f() была выполнена как одно целое
Можно пояснить для чего?