2009-10-17 3 views
1

Должен ли я сделать один экземпляр NSLock в делетете приложения, который будет использоваться всеми классами? Или целесообразно, чтобы каждый класс создавал экземпляр собственного экземпляра NSLock по мере необходимости?Должен ли экземпляр NSLock быть «глобальным»?

Будет ли блокировка работать во втором случае, если бы я, например, имел доступ к контексту управляемого объекта, который распространяется на два контроллера представления?

+0

Будьте очень бойтесь при использовании замков с ручным кодированием и будьте осторожны с необходимостью для них. –

+2

Я не уверен, что это значит. В руководстве по основным данным предлагается блокировать доступ к контексту управляемого объекта, если используется потоковая передача. Что еще я использовал бы, кроме пары «блокировка-разблокировка» NSLock? –

+0

Да, я просто говорил, не смотрю ... в этом случае это уместно. –

ответ

3

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

Теперь, чтобы правильно защитить ваш объект (в критическом разделе кода, в котором несколько объектов могут получить к нему доступ), вы должны использовать САМОЕ БЛОКОВОЕ ИНСТРУКЦИЮ, которое затем должно быть общим для ВСЕХ возможных объектов, обращающихся к объекту, который вы готовы защитить.

Если вашему приложению необходимо защитить объект, к которому может одновременно обращаться большинство классов, то наличие экземпляра с одним замком в порядке. Если вам нужны лучшие результаты (особенно если количество одновременных обращений к вашему объекту велико), вы можете иметь несколько блокировок. Каждая блокировка будет отвечать за разрешение/запрет доступа к определенному атрибуту/полю вашего объекта. Таким образом, несколько объектов могут получить доступ к вашему объекту, изменяя другой атрибут/поле одновременно. Вы в основном увеличиваете количество одновременных операций над своим объектом. Однако каждая блокировка ДОЛЖНА STILL быть разделена между другими объектами, которые будут обращаться к объекту, который вы защищаете.

Наличие экземпляра блокировки для каждого контроллера просто НЕ работает; это НЕ защитит ваш объект от одновременных доступов от других объектов в разных потоках. NSLock реализуется с использованием POSIX pthread mutexes, поэтому его нужно использовать точно так же. Это также четко указано в документации NSLock:

Предупреждение. Класс NSLock использует потоки POSIX для реализации его поведения блокировки. При отправке сообщения разблокировки объекту NSLock вы должны быть уверены, что сообщение отправлено из того же потока, который отправил исходное сообщение блокировки. Разблокировка блокировки из другого потока может привести к неопределенному поведению.

Итак, чтобы сохранить семантику критического раздела, это тот же поток, который получил блокировку, которая отвечает за ее освобождение по завершении. Также обратите внимание, что механизм блокировки предназначен только для быстрых операций, т. Е. Вы должны приобрести блокировку только на короткий промежуток времени, прежде чем ее освободить. Если вам нужно ждать непредсказуемого количества времени, вам нужен другой механизм синхронизации, а именно переменная условия, доступная через класс NSCondition.

Надеюсь, это поможет.

+1

Из документации видно, что для разблокировки также используется тот же замок, который используется для блокировки в определенном потоке. Однако из документации для NSNock не ясно, что один и тот же экземпляр блокировки должен использоваться во всех классах. Я также читаю, что если я использую '[блокировка myLock]' более одного раза, перед выпуском соответствующей '[myLock unlock]', то поток будет заморожен. Поэтому я все еще не уверен, что мне нужно ограничить экземпляр и область действия 'myLock' конкретным вызываемым классом/потоком, или я могу без проблем использовать« myLock »в приложении. –

+0

Я предлагаю прочитать документацию для взаимно устаревших puteread. Вы увидите, что мьютекс (NSLock) должен быть разделен между всеми потоками, которые будут обращаться к объекту, который вы хотите защитить. Обратите внимание, что я не говорю, что он должен делиться глобально по всем потокам: только один из них будет обращаться к вашему объекту. То, что вы говорите о блокировке два раза подряд, является правильным: если мьютекс не рекурсивный, возникает проблема. Чтобы использовать рекурсивные мьютексы, вы должны использовать объект NSRecursiveLock. См. Документацию «Руководство по программированию потоков», в частности раздел «Синхронизация». –

1

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

Смежные вопросы