Использование @synchronized, volatile и OSMemoryBarrier () вместе. Одно подразумевает другое? - PullRequest
8 голосов
/ 25 октября 2011

Исходя из Java, я пытаюсь изучить безопасность потоков в Objective-C. До сих пор я полагался, что

  • @ синхронизированные блоки предотвращают одновременный доступ к одному и тому же блоку кода
  • изменчивые переменные обеспечивают видимость изменений в потоках
  • OSMemoryBarrier (); обеспечивает правильный порядок доступа

Мой вопрос таков: один из них подразумевает один или несколько других? Если я хочу все три, нужно ли мне использовать все три техники?

Пример:

volatile int first = 0;
volatile int second = 0;

[...]

@synchronized {
    OSMemoryBarrier();
    first++;
    OSMemoryBarrier();
    second++;
    OSMemoryBarrier();
}

В Java все три гарантированы при входе и выходе из синхронизированного блока, а также при чтении или записи переменной типа. Правда?

Ответы [ 2 ]

3 голосов
/ 25 октября 2011

Директива @synchronized преобразуется следующим образом ...

- (NSString *)myString {
  @synchronized(self) {
    return [[myString retain] autorelease];
  }
}

становится ...

- (NSString *)myString {
  NSString *retval = nil;
  pthread_mutex_t *self_mutex = LOOK_UP_MUTEX(self);
  pthread_mutex_lock(self_mutex);
  retval = [[myString retain] autorelease];
  pthread_mutex_unlock(self_mutex);
  return retval;
}
2 голосов
/ 21 октября 2016

@ synchronized не защищает блок кода от повторного ввода - он предотвращает выполнение любого кода, который также использует @synchronized с тем же объектом.Таким образом, если у вас есть два метода

- (void)method1 {
    @synchronized (self) { dothis (); }
}
- (void)method2 {
    @synchronized (self) { dothat (); }
}

и два разных потока, вызывающих method1 и method2 для одного и того же объекта, то dothis () и dothat () будут вызываться один за другим.Конечно, это также верно, если два разных потока вызывают method1 для одного и того же объекта.@synchronized не мешает вам вводить блок в том же потоке, поэтому в приведенном выше примере dothis () может вызвать [self method2], и он не будет заблокирован.

Если вы используете volatile или OSMemoryBarrier (), тогда я полагаю, что ваш дизайн слишком, слишком, слишком сложен, и у вас рано или поздно возникнут проблемы.

...