Блокировка тела функции с помощью объекта параметра функции - PullRequest
2 голосов
/ 18 января 2012

Сегодня я наткнулся на этот кусок кода

internal  object UpdatePracownik(object employee)
{  
    lock (employee)
    {
        // rest of the code 
    }

    return employee;
}

Мне было интересно, является ли это правильным решением для блокировки доступа к функции?

Не лучше использовать атрибут

[MethodImpl(MethodImplOptions.Synchronized)] 

вместо замка такого типа?

Ответы [ 3 ]

1 голос
/ 18 января 2012

Использование атрибута MethodImpl для синхронизации метода эквивалентно блокировке объекта, специфичного для метода.

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

Это также означает, что метод синхронизируется сам по себе, но вы можете также заблокировать другие методы, используя тот же идентификатор. Например, вы можете захотеть синхронизировать метод DeletePracownik с UpdatePracownik, чтобы вы не могли удалить один объект во время его обновления.

1 голос
/ 18 января 2012

Ну, это зависит.Если все потоки вызывают этот метод, передавая тот же глобально видимый объект в качестве параметра, то все они будут видеть одну и ту же блокировку, и проблем не будет.

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

Использование предложенного вами метода синхронизации позволяет обернуть все тело метода в оператор lock(this), например:

internal  object UpdatePracownik(object employee)
{
    lock (this)
    {
        // code        
    }
}

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

0 голосов
/ 18 января 2012

Блокировка экземпляра сотрудника - плохая идея, так как блокировка «this» выполняется по той же причине: код, находящийся вне вашего контроля, также может блокировать эти экземпляры и вызывать взаимные блокировки ( blogs.msdn.com / б / bclteam / Архив / 2004/01/20 / 60719.aspx ). Желательно использовать приватный член:

private readonly object _lock = new object();

...

lock (_lock)
{
 ..
}

Кроме того, вам следует ознакомиться с ReaderWriterLockSlim . Часто вам может потребоваться разрешить одновременный доступ к определенным функциям, если только не выполняется операция записи:

private readonly ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim();

public void ReadOp()
{
     _rwLock.EnterReadLock();  //only blocks if write lock held
     try
     {
         //do read op
     }
     finally
     {
         _rwLock.ExitReadLock();
     }
}

public void WriteOp()
{
     _rwLock.EnterWriteLock();  //blocks until no read or write locks held
     try
     {
         //do write op
     }
     finally
     {
         _rwLock.ExitWriteLock();
     }
}
...