Информация об изменениях

Сообщение Как такое сделать без блокировок? от 09.09.2018 10:23

Изменено 09.09.2018 10:28 SergASh

Как такое сделать без блокировок?
Привет всем!

Пусть имеется множество строковых ключей. На нем вводится отношение эквивалетности, порожденное функцией ConstraintExpression.Canonize.
Этих ключей извне приходит большое количество, и по каждому нужно взять объект чтобы выполнить на нем относительно тяжеловесную обработку.
Для ключей в пределах класса эквивалентности вся обработка одинаковая. Однако инициализация перед ее началом занимает много ресурсов.
Поэтому хочется не создавать лишних объектов, а использовать уже существующие по возможности. Например так

public class Factory 
{
  public Constraint Create( string expression )
  {
    lock ( lock_ )
    {
      Constraint candidate;
      if ( map_.TryGetValue( expression, out candidate ) )
      {
        return candidate;
      }

      candidate = new Constraint( expression );
      var canonic = candidate.Canonic;
      
      Constraint result;
      if ( !map_.TryGetValue( canonic, out result ) )
      {
        result = candidate;
        map_[canonic] = result;
      }

      map_[expression] = result;
      return result;
    }
  }

  private readonly IDictionary<string, Constraint> map_ = new Dictionary<string, Constraint>( StringComparer.InvariantCultureIgnoreCase );
  private readonly object lock_ = new object();
}
public class Constraint
{
  public Constraint( string expression )
  {    
    Expression = expression;
    Canonic = Canonize( expression );      
  }
  public string Expression { get; private set; }
  public string Canonic { get; private set; }
  
  public string DoHardWork() {}
  
  private string Canonize( string key ) { return key.ToLower(); } // Только для примера
}

А вопрос в том, можно ли переписать фабрику без блокировок?

Спасибо.
Как такое сделать без блокировок?
Привет всем!

Пусть имеется множество строковых ключей. На нем вводится отношение эквивалетности, порожденное функцией ConstraintExpression.Canonize.
Этих ключей извне приходит большое количество, и по каждому нужно взять объект чтобы выполнить на нем относительно тяжеловесную обработку.
Для ключей в пределах класса эквивалентности вся обработка одинаковая. Однако инициализация перед ее началом занимает много ресурсов.
Инициализация частично отложенная, так что создать новый объект хоть и дороже, чем не создавать его, но гораздо дешевле, чем использовать
новый объект для вызова DoHardWork вместо ранее созданного эквивалентного.

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

public class Factory 
{
  public Constraint Create( string expression )
  {
    lock ( lock_ )
    {
      Constraint candidate;
      if ( map_.TryGetValue( expression, out candidate ) )
      {
        return candidate;
      }

      candidate = new Constraint( expression );
      var canonic = candidate.Canonic;
      
      Constraint result;
      if ( !map_.TryGetValue( canonic, out result ) )
      {
        result = candidate;
        map_[canonic] = result;
      }

      map_[expression] = result;
      return result;
    }
  }

  private readonly IDictionary<string, Constraint> map_ = new Dictionary<string, Constraint>( StringComparer.InvariantCultureIgnoreCase );
  private readonly object lock_ = new object();
}
public class Constraint
{
  public Constraint( string expression )
  {    
    Expression = expression;
    Canonic = Canonize( expression );      
  }
  public string Expression { get; private set; }
  public string Canonic { get; private set; }
  
  public string DoHardWork() {}
  
  private string Canonize( string key ) { return key.ToLower(); } // Только для примера
}

А вопрос в том, можно ли переписать фабрику без блокировок?

Спасибо.