Re: Паралелльное изменение одного объекта
От: Vladek Россия Github
Дата: 12.04.16 09:54
Оценка:
Здравствуйте, e.thrash, Вы писали:

ET>каждый из методов вычисляет и меняет независимые друг от друга данные объекта Car.


Это сейчас так, а как оно будет через полгода-год? Какой код гарантирует, что эти два метода не будут менять одни и те же данные? Или там просто камент с предупреждением висеть будет?

ET>Насколько опасным будет код если эти два метода распаллелить в Task.ContinueWhenAll ?

ET>Нужна ли в данном случае синхронизация?

Всё тайное нужно сделать явным. Разделить Car на два объекта, после вычислений собирать снова в один, например.
Отредактировано 12.04.2016 9:54 Vladek . Предыдущая версия .
Re[3]: Паралелльное изменение одного объекта
От: Sinix  
Дата: 12.04.16 10:00
Оценка:
Здравствуйте, Vladek, Вы писали:

S>>Воспроизвести можно, но нужно постараться.

V> Гораздо вероятнее, что код в будущем изменится и неявное предположение, что параллельный код меняет разные части объекта, станет ложным.

О, подход из серии "мы закладываемся на то, что этот объект никто не будет использовать"? Одобряю.

Если серьёзно, члены типа или поддерживают использование в нескольких потоках, или нет. Большинство instance members в BCL — нет, это соглашение по умолчанию.
Если вы решили отступить от этого контракта, ответственность "спроектировать тип так, чтобы при его использовании не возникало косяков" целиком и полностью ваша
Re: Паралелльное изменение одного объекта
От: SergeyT. США http://sergeyteplyakov.blogspot.com/
Дата: 12.04.16 16:05
Оценка: +2
Здравствуйте, e.thrash, Вы писали:


ET>каждый из методов вычисляет и меняет независимые друг от друга данные объекта Car.

ET>Насколько опасным будет код если эти два метода распаллелить в Task.ContinueWhenAll ?
ET>Нужна ли в данном случае синхронизация?

Если цель распараллелить длительные вычисления отдельных свойств, то лучше так и сделать, а сливать их и обновлять объект уже можно после того, как они вычислены.

Вот псевдокод:


async Task Calculate(Car car)
{
   var priceTask = CalculatePriceAsync(inputForPrice);
   var useTimeTask = CalculateUseTime(inputForUseTime);
   await Task.WhenAll(priceTask, useTimeTask);

   car.Price = priceTask.Result;
   car.UseTime = useTimeTask.Result;
}


Как уже заметили ниже, поскольку вычисляются два разных аспекта, то менять объек Car из разных потоков можно. Но ведь это может измениться (да, это размышления на будущее). Но поскольку разделить вычисления новых значений от изменения объекта car — задача тривиальная и в любом случае лучше разделяет ответственности в коде, то проще поступить так с самого начала: выделить вычисления в отдельные методы, запустить вычисления параллельно, а затем "заджоиниться" и обновить объект, когда обе операции будут завершены.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.