Синхронізація і потокова безпека – JAVA ДЛЯ ANDROID

&nbsp

Коли два або більше працюючих потоку мають доступ до одного і того ж набору змінних, потоки можуть змінювати ці змінні, причому так, що можливе пошкодження даних або порушення логіки одного або декількох з цих потоків Подібні ненавмисні помилки конкурентного доступу називаються порушеннями безпеки потоків (thread safety violations) Їх складно відтворювати, складно знаходити і складно тестувати

У Java прямо не прописані обмеження на доступ декількох потоків до змінних Замість цього в якості основного механізму забезпечення безпеки потоків в Java використовується ключове слово synchronized Це ключове слово серіалізуются доступ до того блоку, який контролює і, що ще важливіше, синхронізує видиме стан між двома потоками Розмірковуючи про паралельність в Java, легко випустити з уваги, що синхронізація одночасно керує і доступом, і видимістю Розглянемо наступну програму:

Можна подумати: «Немає ніякої необхідності синхронізувати змінну shouldStop Дійсно, при доступі до неї між основним і породженим потоком може виникнути конфлікт І що Через секунду породжений потік обовязково встановить значення true Булеві вирази є атомарними Якщо основний потік на даний момент не побачить, що породжений потік має значення true, то, безсумнівно, він побачить породжений потік у значенні true наступного разу » Ця логіка не тільки помилкова, але й небезпечна Вона не враховує дії оптимізують компіляторів і каптірующіх процесорів Програма може ніколи не закінчитися Кожен з двох потоків цілком може використовувати власну копію shouldStop, існуючу тільки в апаратній кеші якого-небудь локального процесора Оскільки синхронізація між двома потоками відсутня, копія кешу, можливо, так і не буде надана в загальний доступ і основний потік ніколи не побачить значення породженого потоку

У Java діє просте правило, що дозволяє уникнути порушення безпеки потоків: коли два різних потоку отримують доступ до одного і того ж змінюваному станом (змінної), весь доступ до цього Станом повинен здійснюватися синхронно, із загальною блокуванням

Деякі розробники порушують це правило, поміркувавши про поведінку спільно використовуваного стану у своїй програмі, намагаючись оптимізувати код Оскільки багато пристроїв, на яких сьогодні використовується платформа Android, не допускають паралельного виконання (замість цього один процесор по черзі використовується всіма потоками), можливо, складеться враження, що програми, в яких порушується описане правило, працюють правильно Проте, коли мобільні пристрої рано чи пізно будуть оснащені декількома багатоядерними процесорами і великими багаторівневими кешами процесорів, неправильно написані програми, швидше за все, будуть страждати від помилок – серйозних, періодичних, які до того ж буде дуже складно знаходити

При реалізації паралельних процесів в Java найкраще користуватися потужними бібліотеками Java util concurrent Тут знайдуться практично будь-які конкурентні структури, які можуть знадобитися, – оптимально реалізовані і протестовані У Java розробникам вже майже не доводиться вдаватися до низькорівневих конкурентним конструкціям, так як це не більш доцільно, ніж винаходити власну реалізацію двонаправленого списку

Ключове слово synchroni zed може застосовуватися в трьох контекстах: для створення блоку, для роботи зі статичним методом або для роботи з динамічним методом При визначенні блоку це ключове слово приймає як аргумент посилання на обєкт, який буде використовуватися в якості семафора Примітивні типи не можуть застосовуватися в якості семафорів, а будь-який обєкт – може

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

Цей спосіб дуже зручний, але користуватися ним потрібно з обережністю Складний клас, що містить безліч активно застосовуваних методів і синхронизирующий їх таким чином, може спровокувати конфлікт при блокировках Якщо кілька зовнішніх потоків спробують одночасно звернутися до фрагментів даних, які не повязані один з одним, то найкраще захистити ці інформаційні фрагменти окремими блокуваннями

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

Нарешті, слід зазначити, що обєктні блокування в Java є багаторазовими (reentrant) Наступний код абсолютно безпечний і не викликає взаимоблокировки (клінчу):

Джерело: Android Програмування на Java для нового покоління мобільних пристроїв

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*