Вопрос про Lazy<T>
От: SergASh  
Дата: 01.12.17 13:51
Оценка:
Привет всем!

Есть контейнер, который выставляет наружу лениво инициализирующийся ресурс.
Вопрос: как потокобезопасно выполнить метод ресурса, но только если он был проинициализирован?

Вот наивная версия
public interface IResource
{
  void Reset();
}

public class Container
{
  public IResource Resource { get { return resource_.Value; } }
  
  public void ResetResource() 
  {
    if ( resource_.IsValueCreated )
    {
      resource_.Value.Reset();
    }
  }

  private Lazy<IResource> resource_ = new Lazy<IResource>( () => new Resource() );
}

Понятно, что можно lock использовать, но может есть способ поумней, учитывая что сам Lazy умеет без блокировок работать?

Спасибо.
Re: Вопрос про Lazy<T>
От: Sinix  
Дата: 01.12.17 14:52
Оценка:
Здравствуйте, SergASh, Вы писали:

SAS>Понятно, что можно lock использовать, но может есть способ поумней, учитывая что сам Lazy умеет без блокировок работать?

Lazy отвечает только за создание ресурса. Так что или lock (общий для всех действий над ресурсом, чтобы не ресетнуть посередине обработчика), или обдумать исходную проблему и написать код так, чтобы в комбо разделяемый доступ + reset не было необходимости.
Re[2]: Вопрос про Lazy<T>
От: SergASh  
Дата: 01.12.17 15:52
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Lazy отвечает только за создание ресурса. Так что или lock (общий для всех действий над ресурсом, чтобы не ресетнуть посередине обработчика), или обдумать исходную проблему и написать код так, чтобы в комбо разделяемый доступ + reset не было необходимости.


Увы, не могу удовлетвориться таким ответом. Хотелось бы чего-то в том же духе, как ConcurrentDictionary выполняет функцию атомарно во вставкой и без блокировки. Видать, придется свой Lazy выдумывать.
Отредактировано 01.12.2017 15:52 SergASh . Предыдущая версия .
Re[3]: Вопрос про Lazy<T>
От: Sinix  
Дата: 01.12.17 15:56
Оценка:
Здравствуйте, SergASh, Вы писали:

SAS>Увы, не могу удовлетвориться таким ответом. Хотелось бы чего-то в том же духе, как ConcurrentDictionary выполняет функцию атомарно во вставкой и без блокировки. Видить придется свой Lazy выдумывать.

Не вопрос, только сначала распишите для себя сценарии, начиная с очевидного
// thread 1:              // thread 2:

var x = lazy.Value
DoThis(x)

                          lazy.Value.Reset()

DoThat(x)


Что-то мне подсказывает, что reset с параллельным использованием плохо сочетается
Re[3]: Вопрос про Lazy<T>
От: Sharov Россия  
Дата: 01.12.17 16:57
Оценка:
Здравствуйте, SergASh, Вы писали:

SAS>Увы, не могу удовлетвориться таким ответом. Хотелось бы чего-то в том же духе, как ConcurrentDictionary выполняет функцию атомарно во вставкой и без блокировки. Видать, придется свой Lazy выдумывать.


Не совсем правильный аналог -- здесь скорее случай транзакционной памяти, что в данном случае равносильно lock.
Кодом людям нужно помогать!
Re: Вопрос про Lazy<T>
От: vorona  
Дата: 02.12.17 09:50
Оценка:
Здравствуйте, SergASh, Вы писали:

ContextBoundObject
Re: Вопрос про Lazy<T>
От: Sinatr Германия  
Дата: 05.12.17 08:10
Оценка:
Здравствуйте, SergASh, Вы писали:

SAS>Привет всем!


SAS>Вопрос: как потокобезопасно выполнить метод ресурса, но только если он был проинициализирован?


Как к вопросу относится Lazy<T>? Или просто, до кучи, "потому что уже так сделано"? (см ниже)

SAS>Понятно, что можно lock использовать, но может есть способ поумней, учитывая что сам Lazy умеет без блокировок работать?


Это вам понятно. Покажите версию с lock, а то не очень-то понятно, что именно вы синхронизируете: доступ к instance (тогда вопрос интересный и имеет отношение к Lazy<T>), доступ к Reset (Albahari в помощь) или доступ к какому-то еще члену.

Вызов Container.Resource.Reset() не требует проверки на IsValueCreated. Подозреваю, что вы хотели так же private constructor (см. singleton), иначе я не прав.
---
ПроГLамеры объединяйтесь..
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.