Що @synchronized () робить як одиночний метод у цілі C?


87

Я щойно створив синглтон-метод, і я хотів би знати, що @synchronized()робить функція , оскільки я часто її використовую, але не знаю значення.

Відповіді:


119

Він оголошує критичний розділ навколо блоку коду. У багатопотоковому коді @synchronizedгарантує, що тільки один потік може виконувати цей код у блоці в будь-який момент часу.

Якщо ви не знаєте, що він робить, то ваша програма, ймовірно, не є багатопотоковою, і вам, ймовірно, не потрібно її використовувати (особливо якщо сам синглтон не захищений від потоків).


Редагувати: Додавання додаткової інформації, якої не було в оригінальній відповіді від 2011 року.

@synchronizedДиректива запобігає кілька потоків від входу будь-якої ділянки коду , який захищений з допомогою @synchronizedдирективи зі посиланням на той же об'єкт . Об'єкт, переданий @synchronizedдирективі, є об'єктом, який використовується як "замок". Два потоки можуть знаходитися в одній захищеній області коду, якщо в якості блокування використовується інший об'єкт, а також ви можете захищати дві абсолютно різні області коду, використовуючи той самий об'єкт, що і замок.

Крім того, якщо ви випадково переходите nilяк об'єкт блокування, замок взагалі не буде прийнятий.


14
Кілька важливих моментів: 1) Якщо ви використовуєте вказівник nil, @synchronizedвін нічого не робить - ви залишаєтесь незахищеними. 2) @synchronizedє повільним .
Hot Licks

Ця відповідь вводить в оману і не повинна бути прийнятою відповіддю. Хоча те, що в ньому сказано, іноді буде правильним (якщо маркер, переданий синхронізованому, є однаковим об’єктом у всіх потоках ), він вводить в оману неповно. синхронізовано заважає виконувати будь-яку кількість пов'язаних розділів коду одночасно, а не просто "цей код у блоці". Параметр, що синхронізується, ефективно визначає, які розділи коду (або «блоки», як їх викликає відповідь), захищені від одночасного доступу.
Арда

@Arda Ви абсолютно праві. Я додав трохи більше інформації та посилання на документацію Apple про @synchronized.
Джон Калсбек,

@JohnCalsbeek, відповідь зараз виглядає набагато кращою. Великі пальці від мене.
Арда

@HotLicks цікаво вказати на це, але ще краще було б коротко сказати, які можуть бути альтернативи (посилання?)
itMaxence

43

З документації Apple тут і тут :

Директива @synchronized - це зручний спосіб створення блокування мьютексу на льоту в коді Objective-C. Директива @synchronized робить те, що робив би будь-який інший блокування mutex - вона заважає різним потокам отримувати один і той же замок одночасно.

Документація містить велику інформацію з цього питання. Варто витратити час, щоб прочитати його, особливо враховуючи те, що ви користувались ним, не знаючи, що він робить.


26

@synchronizedДиректива являє собою зручний спосіб для створення м'ютекс замки на льоту в Objective-C код.

@synchronizedДиректива робить те , що будь-який інший замок м'ютекс робитиме-он запобігає різні потоки від придбання такої ж замок одночасно.

Синтаксис:

 @synchronized(key) 
 { 
  // thread-safe code 
 }

Приклад:

 -(void)AppendExisting:(NSString*)val
{
  @synchronized (oldValue) {
      [oldValue stringByAppendingFormat:@"-%@",val];
  }
}

Тепер наведений вище код ідеально безпечний для потоків. Тепер кілька потоків можуть змінити значення.

Вище - лише неясний приклад ...


3
Чи не повинно бути @synchronized (oldValue)?
Джоель

Або навіть @synchronized(val, oldValue) { ... }?
Валентин Шергін

Я не впевнений, що коли-небудь бачив будь-яку схему, яка була б "абсолютно безпечною для потоків". Принаймні, вам потрібно знати, що ви робите, а не просто сліпо копіювати десь код.
Hot Licks

Але я припускаю, що згаданий вище код "ідеально безпечний для потоків", адже він абсолютно нічого не робить.
Hot Licks

6

@synchronized block автоматично обробляє блокування та розблокування для вас . @synchronize у вас є неявна блокування, пов’язана з об’єктом, який ви використовуєте для синхронізації. Ось дуже інформативна дискусія на цю тему. Будь ласка, дотримуйтесь Як @synchronized блокування / розблокування в Objective-C?



-2

@synchronizedє thread safeмеханізмом. Шматок коду, записаний всередині цієї функції, стає частиною critical section, яку одночасно може виконувати лише один потік.

@synchronizeзастосовує блокування неявно, тоді як NSLockзастосовує його явно.

Це лише забезпечує безпеку нитки, а не гарантує це. Я маю на увазі, що ви наймаєте для свого автомобіля досвідченого водія, але це не гарантує, що автомобіль не зіткнеться з ДТП. Однак ймовірність залишається найменшою.


2
Це абсолютно неправильно. dispatch_once НЕ робить те саме, що @syncrhonized, це може бути заміною ТІЛЬКИ при виділенні сингтона.
jugutier
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.