замок (новий об'єкт ()) - культ вантажу чи якийсь божевільний "мовний особливий випадок"?


87

Я переглядаю якийсь код, написаний консультантом, і хоча десятки червоних прапорів уже з’явилися, я не можу обернути голову навколо такого фрагмента:

private void foo()
{
    if (InvokeRequired)
    {
        lock (new object())
        {
            if (m_bar!= null)
                Invoke(new fooDelegate(foo), new object[] { });
        }
    }
    else
    {
        if(OnBazChanged != null)
            OnBazChanged();
    }
}

Що тут робить lock (new object ())? Це не повинно мати жодного ефекту, оскільки воно завжди блокується на інший об’єкт, але такий тип блокування постійний у всьому коді, навіть у частинах, які не копіюються та вставляються. Це якийсь особливий випадок у мові C #, який компілюється до чогось, про що я не знаю, чи програміст просто прийняв якийсь культ вантажу, який спрацював деякий час тому?


19
Думаю, вони дуже розгублені. Вони, напевно, бачили це там, де new object()зберігалося в полі, і це поле використовувалось у lock()висловлюваннях, і вони не знали, що краще не вбудовувати його.
Damien_The_Unbeliever

21
У цього "консультанта" є кілька пояснень ... Ви не помиляєтесь: цей lockкод абсолютно марний
Марк Гравелл

12
@Baboon: Тільки якщо ти не той, хто повинен робити рефакторинг ...

2
Плюс, якщо це WinForms, то я не можу зрозуміти, чому взагалі там повинен бути замок.
Дрю Ноукс

7
Видаліть його, а потім повторно запустіть свій набір тестів на 100% покриття коду. Що це? Попередній консультант не зробив такого?
Spacedman

Відповіді:


82

Я б не здивувався, якби це побачив хтось:

private readonly object lockObj = new object();

private void MyMethod()
{
    lock(lockObj)
    {
        // do amazing stuff, so amazing it can only run once at a time
        // e.g. comands on the Mars Rover, or programs on iOS pre 4 / 5 ??
    }
}

і думав, що зможе скоротити кількість рядків.

Я б дуже хвилювався, якби це було так ...


4
Він міг побачити метод, який називається "newObject ()", і цей метод повернув екземпляр синглтона, але він сказав "агов, хіба c # не має для цього ключових слів"?
Amiram Korach

9
Це справді звучить як робота з рефакторингу, без ефективного розуміння того, що відбувається.
Афеліон

1
@OrangeDog: На жаль, це неможливо, оскільки відповідний код був написаний до мого приходу в компанію. Тепер, коли потрібно внести зміни, можливо, я можу переконати керівництво дозволити мені виправити код. В іншому випадку я не буду нести відповідальність за будь-які нестабільності (останній, хто торкнеться чогось, той винен) ...

2
@Ibruder Вищим пріоритетом було б переконати керівництво в тому, що їм потрібен контроль версій, автоматизовані системи тестування та огляду. Якщо останній, хто чогось торкнувся, той винен, то це не схоже на дуже хорошу компанію, на яку можна працювати.
OrangeDog

1
Мені мало до того, що очевидно зламане блокування - всі інші вже на це вказували, але +1 лише для for або програми на iOS до 4/5 '<g>
Мартін Джеймс,

15

Ось подібне запитання та відповідь:

Замки забезпечують взаємне виключення - не більше однієї нитки може утримувати замок одночасно. Блокування ідентифікується з конкретним екземпляром об’єкта. Ви створюєте новий об'єкт для блокування кожного разу, і у вас немає жодного способу повідомити будь-який інший потік для блокування саме цього екземпляра об'єкта. Тому ваш замок марний.


2

Це, мабуть, марно. Але є шанс створити бар’єр пам’яті саме там. Не впевнений, що c # блокує elision чи зберігає семантику упорядкування блокування.


Це було кілька років тому, але, чоловіче, ти цілком заслужив +1 за те, що заявив цей очевидний факт, який деякі люди повністю проігнорували. Наприклад, на універсальній платформі Windows не існує методу MemoryBarrier (), а магія з Interlocked. CompareExchange та lock (new Object ()) стають єдиними способами вирішення деяких проблем.
Sergey.quixoticaxis.Ivanov

Я навіть не знав, що C # це дозволив. Чудово з вашої уваги.
Всі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.