Вопрос

Я программист на Java и знаю несколько вещей о многопоточности в Java.

В Java я могу заблокировать метод с помощью синхронизированного ключевого слова:

private int a;
private int b;
private int c;
private synchronized void changeVars()
{
  a = 4;
  b = 2;
  c = a+b;
}

Я искал в msdn и увидел, что в c # есть несколько игрушек для игры с потоками. Например, monitor.Enter, monitor.Exit, блокировка или расширенный мьютекс.

Но мне нужно синхронизировать один метод. Что эквивалентно этому в c #?

Заранее спасибо.

Это было полезно?

Решение

Что-то вроде этого, возможно,

using System.Runtime.CompilerServices;

...

private int a;
private int b;
private int c;

[MethodImpl(MethodImplOptions.Synchronized)]
private void changeVars()
{
  a = 4;
  b = 2;
  c = a+b;
}

Другие советы

В C # нет прямого эквивалента, но вы можете сделать то же самое с этим:

private readonly object changeVarsLockObject = new object();

private void changeVars()
{
  lock(changeVarsLockObject)
  {
    a = 4;
    b = 2;
    c = a+b;
  }
}

Просто чтобы прояснить: объявление метода, синхронизированного в Java, требует, чтобы вызывающая сторона удерживала монитор на объекте , к которому был вызван метод (который является объектом Class для статических методов).

То есть вы можете "заблокировать метод" вводит в заблуждение, поскольку вы не полностью блокируете этот метод (один и тот же метод все еще может быть вызван для разных объектов экземпляра), и вы блокируете больше , чем этот метод (никакой другой бит кода, который не требует целевого объекта Монитор, включая другие синхронизированные методы или явные приобретения, может работать одновременно).

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

Итак, хотя это не тот однострочный ответ, который вы искали, я собираюсь утверждать, что любой однострочный ответ обречен на провал без знания всей экосистемы, подкрепляющего его. Таким образом, вы должны прочитать хорошую книгу / учебное пособие по синхронизации в C #, а не пытаться переводить ваш опыт Java по ключевым словам.

Прямой эквивалент этого - использование блокировки (this):

private void ChangeVars()
{
    lock (this) {
        a = 4;
        b = 2;
        c = a+b;
    }
}

или действительно с использованием MethodImplAttribute, как описано R. Bemrose, что равносильно тому же:

[MethodImpl(MethodImplOptions.Synchronized)]
private void ChangeVars()
{
    a = 4;
    b = 2;
    c = a+b;
}

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

private object monitor = new object();
private void ChangeVars()
{
    lock (monitor) {
        a = 4;
        b = 2;
        c = a+b;
    }
}

Предпочтительное решение - заключить тело метода в оператор lock .

internal class Foo
{
   private Object lockObject = new Object();

   private void ChangeVars()
   {
      lock (this.lockObject)
      {
         // Manipulate the state.
      }
   }
}

Вы также можете использовать декларативную синхронизацию, но у этого есть очевидный недостаток, который вы должны извлечь из ContextBoundObject и все методы, оформленные с помощью Synchronization совместно используют один и тот же объект блокировки, ограничивая степень детализации блокировки.

internal class Foo : ContextBoundObject
{
   [Synchronization]
   private void ChangeVars()
   {
      // Manipulate the state.
   }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top