C#'??' ориентированный на многопотоковое исполнение оператор?

Это прекрасно работает.

function calculateMinutes(DateInterval $int){
    $days = $int->format('%a');
    return ($days * 24 * 60) + ($int->h * 60) + $int->i;
}
8
задан Peter Mortensen 1 December 2009 в 18:09
поделиться

6 ответов

НАЧАТЬ РЕДАКТИРОВАНИЕ

Судя по вашему отредактированному заголовку, сам оператор объединения с нулем кажется потокобезопасным (см. анализ Фила Хаака ). Однако похоже, что это не гарантирует от возможных множественных вызовов конструктора StringBuilder.

КОНЕЦ РЕДАКТИРОВАНИЯ

У вас есть большая проблема с потоковой передачей, и это то, что свойство Builder само представляет состояние, которое может быть общий для потоков. Даже если вы сделаете ленивую инициализацию потокобезопасной, нет никакой гарантии, что методы, использующие Builder, делают это потокобезопасным способом.

// below code makes the getter thread safe
private object builderConstructionSynch = new object();
public StringBuilder Builder
{
    get
    {
        lock (builderConstructionSynch)
        {
            if (_builder == null) _builder = new StringBuilder();
        }
        return _builder;
    }
}

Вышеупомянутое предотвратит проблему с потоками при отложенной инициализации _builder, но если вы не синхронизируете свои вызовы с методы экземпляра StringBuilder, вы re не гарантирует потокобезопасность в любых методах, использующих свойство Builder. Это связано с тем, что методы экземпляра в StringBuilder не предназначены для обеспечения потоковой безопасности. См. Приведенный ниже текст со страницы MSDN StringBuilder .

Любой общедоступный статический (общий в Visual Basic) члены этого типа являются потоками сейф. Члены экземпляра не являются гарантированно потокобезопасный.

Если вы используете StringBuilder в нескольких потоках, вам, вероятно, лучше будет инкапсулировать его в своем классе. Сделайте Builder закрытым и укажите, какое поведение вам нужно, как общедоступный метод:

public void AppendString(string toAppend)
{
    lock (Builder)
    {
        Builder.Append(toAppend);
    }
}

Таким образом, вы не будете писать код синхронизации повсюду.

10
ответ дан 5 December 2019 в 05:08
поделиться

Это не более или менее потокобезопасно; у вас все еще может быть два потока, выполняющих нулевую проверку одновременно, таким образом создавая отдельные объекты и не видя друг друга.

10
ответ дан 5 December 2019 в 05:08
поделиться

НЕТ для обеих версий

8
ответ дан 5 December 2019 в 05:08
поделиться

Я сам не тестировал этот подход, но если вам нужна безопасность потоков без накладных расходов на схему блокировки и вы не беспокоитесь о возможном создании и удалении экземпляра объекта, вы можете попробовать следующее:

using System.Threading;

public StringBuilder Builder
{
    get 
    {
        if (_builder != null)
            Interlocked.CompareExchange( ref _builder, new StringBuilder(), null );
        return _builder; 
    }
}

Вызов CompareExchange () выполнит атомарную замену значения в _builder с новым экземпляром StringBuilder, только если _builder == null.Гарантировано, что все методы класса Interlocked НЕ будут вытеснены переключателями потоков.

2
ответ дан 5 December 2019 в 05:08
поделиться

Нет, ни один из них не является атомарным

2
ответ дан 5 December 2019 в 05:08
поделиться

Приведенные ответы верны, оба не являются потокобезопасными. Фактически, они в основном эквивалентны, а оператор ?? - это просто волшебство компилятора, позволяющее сделать код более компактным. Вам нужно использовать какой-нибудь механизм синхронизации, если вы хотите, чтобы это стало потокобезопасным.

2
ответ дан 5 December 2019 в 05:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: