Непередача управления другому потоку
От: Аноним  
Дата: 24.02.11 04:35
Оценка:
У меня есть вызовы функция которая делает несколько вызовов:

public void f()
{
f1();
f2();
f3();
}


Что нужно сделать чтобы во время выполнения f() передача другому поктоку не произошла? Надо чтобы f() была выполнена как одно целое .

Спасибо!
Re: Непередача управления другому потоку
От: Lloyd Россия  
Дата: 24.02.11 04:43
Оценка:
Здравствуйте, Аноним, Вы писали:

А>
private readonly object _lock = new object();
А>public void f()
А>{
lock (_lock) {
А>f1();
А>f2();
А>f3();
}
А>}
А>


А>Что нужно сделать чтобы во время выполнения f() передача другому поктоку не произошла? Надо чтобы f() была выполнена как одно целое .
Re[2]: Непередача управления другому потоку
От: Sinix  
Дата: 24.02.11 05:59
Оценка: 48 (1)
Здравствуйте, Lloyd, Вы писали:

L>lock (_lock) {

На всякий уточню для топикстартера: код во всех остальных потоках тоже должен использовать lock для обращений к общему ресурсу (методам, объекту — неважно).

И, такие вопросы возникают внезапно, лучше пересмотреть подход к задаче.
Re[3]: Непередача управления другому потоку
От: Аноним  
Дата: 24.02.11 16:11
Оценка:
Здравствуйте, Sinix, Вы писали:
Здравствуйте, Lloyd, Вы писали:

спасибо всем

L>>lock (_lock) {

S>На всякий уточню для топикстартера: код во всех остальных потоках тоже должен использовать lock для обращений к общему ресурсу (методам, объекту — неважно).
почему? можно пример, пожалуйста


S>И, такие вопросы возникают внезапно, лучше пересмотреть подход к задаче.

почему?
Re[4]: Непередача управления другому потоку
От: Sinix  
Дата: 24.02.11 16:54
Оценка:
Здравствуйте, Аноним, Вы писали:

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", она там и останется, так? Для многопоточного — не так. И вот чтобы победить это маленькое "не так", не превращая весь код обратно в однопоточный, наворочено столько, что самому страшно. Короче говоря, не надо туда лезть без особой необходимости, изучения матчасти и ясного понимания того, что делаешь
Re[5]: Непередача управления другому потоку
От: Pavel Dvorkin Россия  
Дата: 24.02.11 17:09
Оценка:
Здравствуйте, 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() снова все запустить.
Re: Непередача управления другому потоку
От: AlexNek  
Дата: 27.02.11 21:38
Оценка:
Здравствуйте, Аноним, Вы писали:

> У меня есть вызовы функция которая делает несколько вызовов:


>
> public void f()
> {
> f1();
> f2();
> f3();
> }
>


> Что нужно сделать чтобы во время выполнения f() передача другому поктоку не произошла? Надо чтобы f() была выполнена как одно целое.

Нужно что бы остальные потоки ждали разрешения на продолжение работы, а разрешение даст выход из функции f1.

Допустим так как здесь

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

Ну, и я надеюсь что "передача другому контролируемому мной потоку не произошла".

>Надо чтобы f() была выполнена как одно целое

Можно пояснить для чего?
avalon 1.0rc3 rev 380, zlib 1.2.3
Re: Непередача управления другому потоку
От: андрей_к Россия  
Дата: 28.02.11 07:17
Оценка:
Добрый день.

Замечательная статья
Автор(ы): Joseph Albahari
Дата: 27.06.2007
Окончание статьи, опубликованной в RSDN Magazine #1-2007. Рассматриваются особенности взаимодействия с апартаментами, потоковые таймеры, пулы потоков, BackgroundWorker, асинхронные методы и делегаты.
В статье использован материал из книги Joseph Albahari, Ben Albahari "C# 3.0 in a Nutshell" — http://www.oreilly.com/catalog/9780596527570/
, правда уже немного старовата.
Думаю Wait и Pulse вполне подойдет.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.