потокобезопасный объект-одиночка в target-c? - PullRequest
3 голосов
/ 06 января 2012

Как создать потокобезопасный одноэлементный объект в target-c.напримерЕсли у меня есть общий контроллер данных, который является одноэлементным объектом, что произойдет, если два или более потоков будут получать к нему доступ одновременно?Или эти объекты по умолчанию имеют безопасность потоков ..?

update :

В этом сценарии объекты в свойстве контроллера данных решают, является ли он потокобезопасным илине ..?Как у моего контроллера данных есть NSMutableArray, и он установлен неатомно, это не будет потокобезопасным.Что произойдет с его значением в этом случае?

обновление: 2

А что на самом деле делает @synchronized(self) ..?

Ответы [ 2 ]

5 голосов
/ 06 января 2012

Если контроллер данных не является потокобезопасным, то может произойти неопределенное поведение - избегайте его любой ценой =)

Объекты NSO определенно не по умолчанию безопасны для потоков.Использование атомарных свойств не делает класс поточным*).

Когда я говорю «изменяемое состояние», я имею в виду объект, который может мутировать внешне или внутренне.Если вы не уверены, заблокируйте, чтобы типы читались или записывались из нескольких потоков.Это должно происходить при чтении и письме - всегда.Если у вас много чтения, блокировка чтения-записи может быть лучше, более специализированной блокировкой.

Чтобы ответить более подробно, вам придется опубликовать некоторый код.

Обновление

В этом сценарии объекты внутри свойства контроллера данных решают, является ли он потокобезопасным или нет ..?Как у моего контроллера данных есть NSMutableArray, и он установлен неатомно, это не будет потокобезопасным.Что будет с его значением в этом случае?

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

Для простоты я продемонстрирую использование @synchronize:

@interface MONCookie : NSObject <NSCopying>

- (NSString *)name;

@end

@interface MONDataController : NSObject
{
@private
  NSMutableArray * cookies; // << MONCookie[]
}

- (void)addCookie:(MONCookie *)cookie;

- (MONCookie *)cookieWithName:(NSString *)name;

@end

@implementation MONDataController

- (id)init
{
  // no lock required here
  self = [super init];
  if (nil != self) {
    cookies = [NSMutableArray new];
  }
  return self;
}

- (void)dealloc
{
  // no lock required here
  [cookies release], cookies = nil;
  [super dealloc];
}

- (void)addCookie:(MONCookie *)cookie
{
  @synchronized(self) { // now accessing cookies - lock required
    [cookies addObject:cookie];
  }
}

- (MONCookie *)cookieWithName:(NSString *)name
{
  MONCookie * ret = nil;
  @synchronized(self) { // now accessing cookies - lock required
    for (MONCookie * at in cookies) {
      if ([at.name isEqualToString:name]) {
        ret = [at copy]; // << give them a copy if cookie is not threadsafe
      }
    }
  }
  return [ret autorelease];
}

@end

Обновление 2

@synchronized устанавливает блокировку уровня объекта.Вы можете думать об этом как о рекурсивной (или повторно входящей) блокировке, эксклюзивной для вашего экземпляра.Это также довольно медленно по сравнению с другими подходами блокировки.Приведенный выше код использует его, он безопасен для потоков и эквивалентен удержанию рекурсивной блокировки, блокировке и разблокировке на границах @synchronized.

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

Я не программировал в цели C раньше, но, насколько я знаю из курса по операционным системам, вы должны поместить общую логическую переменную в ваш одноэлементный объект, такой как boolean isLocked, и каждый раз, когда поток пытается обратиться к этому классу, он долженсделайте следующее.насколько я помню, это называется строгим чередованием :) добрых старых школьных дней.

Тема A:

if(!isLocked) {
isLocked = True;
Do the stuff
isLocked = False;
}
...