Тази статия е огледална статия за машинен превод, моля, кликнете тук, за да преминете към оригиналната статия.

Изглед: 46741|Отговор: 7

[Източник] Волатилни срещу блокирани срещу заключени

[Копирай линк]
Публикувано в 27.08.2018 г. 14:40:35 ч. | | |
Да кажем, че има клас, който съдържа публично int броячно поле, достъпно от няколко нишки, и това число само ще се увеличава или намалява.

При добавяне на това поле, коя от следните схеми трябва да се използват и защо?

  • lock(this.locker) this.counter++;
  • Interlocked.Increment (реф. this.counter);
  • Променете модификатора за достъп на counter на публичен волатилен


Най-лошото (нито един от тях не работи)

Променете модификатора за достъп на counter на публичен волатилен

Този подход всъщност изобщо не е сигурен, а същността при волатилността е, че множество нишки, работещи на няколко процесора, буферират данните и пренареждат изпълнените инструкции.

Ако е неволатилен, когато CPU A се увеличава с определена стойност, CPU B трябва да изчака известно време, за да види увеличената стойност, което може да доведе до проблеми.

Ако е волатилен, това гарантира, че и двата процесора виждат една и съща стойност едновременно. Но това не избягва кръстосаните операции по четене и запис.

Добавянето на стойност към променлива всъщност изисква три стъпки

1. Четене, 2. Добави 3. Пиши

Да предположим, че нишка A чете стойността на брояча като 1 и не е готова да увеличи, тогава нишка B също чете стойността на брояча като 1, и след това и двете нишки започват да извършват инкрементални и записни операции. Стойността на последния брояч е 2. Това не е вярно, и двете нишки са извършили операция за увеличаване и правилният резултат трябва да е 3. Затова етикетирането като нестабилно е просто опасно.

По-добре е

lock(this.locker) this.counter++;

Така е безопасно (разбира се, не забравяйте да заключвате навсякъде, където искате да имате достъп до този брояч). Това предотвратява изпълнението на заключения код от която и да е друга нишка. Освен това предотвратява проблема с последователността на инструкциите при многопроцесорни процесори, споменат по-горе. Проблемът е, че заключването е бавно в производителността и ако го използваш на други несвързани места, може да блокира другите ти нишки.

Най-добро

Interlocked.Increment (реф. this.counter);

Това е безопасно и много ефективно. Извършва четене, увеличаване, записване на три операции в един атом, без да бъде прекъснат по средата. Тъй като това не влияе на другите кодове, не е нужно да помниш заключванията другаде. И е много бърз (както казва MSDN, при днешните процесори често е просто инструкция).

Но не съм напълно сигурен дали може да реши проблема с подреждането на инструкциите на процесора, или трябва да се използва заедно с волатилния и този инкремент.

Допълнение: Кои проблеми решава волатилният предмет добре?

Тъй като волатилното не може да предотврати мултитрединга, какво може да направи? Добър пример е, че имате две нишки, едната винаги записва към променлива, да кажем, че тази променлива е queneLength, а другата винаги чете данни от тази променлива. Ако queueLenght не е волатилен, нишка A може да чете 5 пъти, но нишка B може да види забавени данни или дори данни в грешен ред. Едно решение е да използваш lock, но в този случай можеш да използваш и волатил. Това гарантира, че нишка Б винаги вижда най-новите данни, написани от нишка А, но тази логика работи само ако не ги четете при писане и ако не ги записвате при четене. След като няколко нишки искат да извършват операции по четене-модифициране-записване, трябва да използвате Interlocked или lock.





Предишен:Метод за криптиране на Java MD5
Следващ:Linq имплементира не е в и в условни заявки в SQL
Публикувано в 29.08.2018 г. 16:21:42 ч. |
Здравейте, кодът, който направи по-рано, който комбинира хистограми с високи диаграми и пробиваеми хистограми? Бих искал да попитам дали можете да изпратите код, който може да се редактира на https://jshare.com.cn/demos/hhhhDz?hc-theme=grid-light интерфейса?
Публикувано в 29.08.2018 г. 16:22:13 ч. |
Цялата мрежа е просто вашият ресурс.
Публикувано в 29.08.2018 г. 16:22:55 ч. |
Защото преди 90 години не можеше да остави съобщение. Така че
Публикувано в 29.08.2018 г. 16:40:40 ч. |
Удобно ли е да добавя контактна информация? Консултирай се с теб
 Хазяин| Публикувано в 15.09.2018 г. 13:10:16 ч. |
private static int safeInstanceCount = 0; Оперирайте с атоми
System.Threading.Interlocked.Increment(ref safeInstanceCount); Самоувеличаване 1
System.Threading.Interlocked.Decrement(ref safeInstanceCount); Self-минус 1
Публикувано в 21.05.2020 г. 16:43:54 ч. |
Подкрепете собственика да сподели
 Хазяин| Публикувано в 11.06.2020 г. 15:00:16 ч. |
1. Концепция

В многопоточна среда, операции, които не се прекъсват от механизми за планиране на нишки; След като тази операция започне, тя се изпълнява до края, без никаква превключване на контекста (превключване към друга нишка) между тях.

2. Клас

System.Threading.Interlocked статичен клас

3. Често използвани функции (виж останалите)

1. публичен статичен int Decrement (реф. int location); Декринете стойността на зададената променлива под формата на атомна операция и съхранете резултата

Еквивалентно на lock(obj){i--; }

2. публичен статичен int Increment(референтно int location); Увеличи стойността на зададената променлива под формата на атомна операция и съхрани резултата

Еквивалентно на lock(obj){i++; }
Отричане:
Целият софтуер, програмни материали или статии, публикувани от Code Farmer Network, са само за учебни и изследователски цели; Горното съдържание не трябва да се използва за търговски или незаконни цели, в противен случай потребителите ще понесат всички последствия. Информацията на този сайт идва от интернет, а споровете за авторски права нямат нищо общо с този сайт. Трябва напълно да изтриете горното съдържание от компютъра си в рамките на 24 часа след изтеглянето. Ако ви харесва програмата, моля, подкрепете оригинален софтуер, купете регистрация и получете по-добри услуги. Ако има нарушение, моля, свържете се с нас по имейл.

Mail To:help@itsvse.com