Атамарнага аперацыі і шматструменнасць

Нядаўна я чытаў падручнік, у якім я наткнуўся на заяву, што кажа ..

«Спецыфікацыя мовы гарантуе Java, што для чытання або запісы зменнай з'яўляецца атамарна аперацыяй (калі зменная мае тып доўгай або двайны ). Аперацыі зменныя тыпу доўгі або двайны толькі атамарным, калі яны аб'яўленыя з лятучага Ключавое слова «.

AtomicInteger or AtomicLong that provides methods like getAndDecrement(), getAndIncrement() and getAndSet() which are atomic.

Я заблытаўся трохі з вышэйпаказаным заявай .. маглі б вы ўдакладніць, <�моцны> калі выкарыстоўваць AtomicInteger або AtomicLong класы.

22

11 адказы

Выкананне а = 28 (з кодам <> а з'яўляюцца Int ) з'яўляецца атамарна аперацыяй. Але рабіць а ++ не з'яўляецца атамарна аперацыя, паколькі яна патрабуе чытання значэння а, з прырашчэннем, і запісаць у выніку. У выніку, калі вы выкарыстоўвалі A ++ рэалізаваць струменева-лічыльнік, вы можаце мець два патокі счытвання значэння адначасова (26, напрыклад), то ёсць і павялічваць яго і запісы яго адначасова, у выніку чаго 27 як вынік, замест 28.

AtomicInteger вырашае гэтую праблему, падаючы атамарнага аперацыі, як тыя, якія вы пералічылі. У маім прыкладзе, вы павінны выкарыстоўваць incrementAndGet() , напрыклад, які гарантаваў бы канчатковае значэнне складае 28, а не 27.

43
дададзена
<�Код> а = 28 не гарантуецца, калі атамная а доўгі ці двайны, калі яна не з'яўляецца таксама зменлівыя.
дададзена аўтар assylias, крыніца
доўга і двойчы не з'яўляюцца атамарнага ў 32-бітных віртуальных машынах, таму што яны з'яўляюцца 8 байт. Яны з'яўляюцца непадзельнымі ў 64-бітных JVM.
дададзена аўтар fracca, крыніца
Зноў жа, няма. Атамарнага гэта паняцце робіць аперацыю атамарна, гэта значыць, якое не можа быць напалову назіралася якой-небудзь іншай ніткай. Ён не забяспечвае сінхранізацыю.
дададзена аўтар JB Nizet, крыніца
@HarishAmarnath няма. Правільная сінхранізацыя з'яўляецца спосабам, каб забяспечыць атамарнага, хоць.
дададзена аўтар JB Nizet, крыніца
@assylias: да. Я не паўтараю, таму што гэта было ўжо правільна паказана ў пытанні. Я буду кіраваць, каб удакладніць, хоць.
дададзена аўтар JB Nizet, крыніца
Калі вы выкарыстоўваеце AtomicXxx, вам не трэба выкарыстоўваць лятучымі, як і атамныя аб'екты забяспечваюць больш гарантый, чым няўстойлівыя. Выкананне A ++ на лятучым цэлае ня робіць аперацыю атамарна. Гэта толькі гарантуе іншы паток будзе бачыць новае значэнне а пасля таго, як яно было павялічана. Пры прызначэнні новых значэнняў доўгіх або падвойных значэнняў, ён таксама гарантуе, што запіс з'яўляецца атамарна аперацыяй (з-за запісы ў энерганезалежнай доўгай або двайны зменнай складаецца ў пісьмовай форме 4 байта, а затым запісу іншых 4 байта). Аддаюць перавагу атамныя аб'екты больш лятучых зменнымі ў цэлым.
дададзена аўтар JB Nizet, крыніца
Тады чаму мы павінны выкарыстоўваць «лятучыя», калі мы выконваем аперацыі над зменнымі тыпу «двайны» ці «доўгай»?
дададзена аўтар MaheshVarma, крыніца
так, атамарнага забяспечвае сінхранізацыю?
дададзена аўтар Harish Amarnath, крыніца
@JBNizet, то , атамарнага забяспечвае сінхранізацыю на агульных зменных/аб'ектаў, праўда?
дададзена аўтар Harish Amarnath, крыніца

Выкананне а = 28 (з кодам <> а з'яўляюцца Int ) з'яўляецца атамарна аперацыяй. Але рабіць а ++ не з'яўляецца атамарна аперацыя, паколькі яна патрабуе чытання значэння а, з прырашчэннем, і запісаць у выніку. У выніку, калі вы выкарыстоўвалі A ++ рэалізаваць струменева-лічыльнік, вы можаце мець два патокі счытвання значэння адначасова (26, напрыклад), то ёсць і павялічваць яго і запісы яго адначасова, у выніку чаго 27 як вынік, замест 28.

AtomicInteger вырашае гэтую праблему, падаючы атамарнага аперацыі, як тыя, якія вы пералічылі. У маім прыкладзе, вы павінны выкарыстоўваць incrementAndGet() , напрыклад, які гарантаваў бы канчатковае значэнне складае 28, а не 27.

43
дададзена
<�Код> а = 28 не гарантуецца, калі атамная а доўгі ці двайны, калі яна не з'яўляецца таксама зменлівыя.
дададзена аўтар assylias, крыніца
доўга і двойчы не з'яўляюцца атамарнага ў 32-бітных віртуальных машынах, таму што яны з'яўляюцца 8 байт. Яны з'яўляюцца непадзельнымі ў 64-бітных JVM.
дададзена аўтар fracca, крыніца
@HarishAmarnath няма. Правільная сінхранізацыя з'яўляецца спосабам, каб забяспечыць атамарнага, хоць.
дададзена аўтар JB Nizet, крыніца
Зноў жа, няма. Атамарнага гэта паняцце робіць аперацыю атамарна, гэта значыць, якое не можа быць напалову назіралася якой-небудзь іншай ніткай. Ён не забяспечвае сінхранізацыю.
дададзена аўтар JB Nizet, крыніца
@assylias: да. Я не паўтараю, таму што гэта было ўжо правільна паказана ў пытанні. Я буду кіраваць, каб удакладніць, хоць.
дададзена аўтар JB Nizet, крыніца
Калі вы выкарыстоўваеце AtomicXxx, вам не трэба выкарыстоўваць лятучымі, як і атамныя аб'екты забяспечваюць больш гарантый, чым няўстойлівыя. Выкананне A ++ на лятучым цэлае ня робіць аперацыю атамарна. Гэта толькі гарантуе іншы паток будзе бачыць новае значэнне а пасля таго, як яно было павялічана. Пры прызначэнні новых значэнняў доўгіх або падвойных значэнняў, ён таксама гарантуе, што запіс з'яўляецца атамарна аперацыяй (з-за запісы ў энерганезалежнай доўгай або двайны зменнай складаецца ў пісьмовай форме 4 байта, а затым запісу іншых 4 байта). Аддаюць перавагу атамныя аб'екты больш лятучых зменнымі ў цэлым.
дададзена аўтар JB Nizet, крыніца
Тады чаму мы павінны выкарыстоўваць «лятучыя», калі мы выконваем аперацыі над зменнымі тыпу «двайны» ці «доўгай»?
дададзена аўтар MaheshVarma, крыніца
@JBNizet, то , атамарнага забяспечвае сінхранізацыю на агульных зменных/аб'ектаў, праўда?
дададзена аўтар Harish Amarnath, крыніца
так, атамарнага забяспечвае сінхранізацыю?
дададзена аўтар Harish Amarnath, крыніца

Атамны азначае, што аперацыя завяршаецца без магчымасці нешта здарыцца паміж імі. напрыклад. getAndDecrement (), на AtomicInteger, гарантуе, што пераменная вяртаецца і памяншаецца ў той жа самы час.

Калі б не было атамарна аперацыяй, магчымасць будзе існаваць значэнне, каб атрымаць декрементируется (напрыклад. Ад 3 да 2), а затым мадыфікаваная іншым патокам (напрыклад. Змена яго ад 2 да 5), а затым вяртаецца ў выглядзе 5.

6
дададзена

Атамны азначае, што аперацыя завяршаецца без магчымасці нешта здарыцца паміж імі. напрыклад. getAndDecrement (), на AtomicInteger, гарантуе, што пераменная вяртаецца і памяншаецца ў той жа самы час.

Калі б не было атамарна аперацыяй, магчымасць будзе існаваць значэнне, каб атрымаць декрементируется (напрыклад. Ад 3 да 2), а затым мадыфікаваная іншым патокам (напрыклад. Змена яго ад 2 да 5), а затым вяртаецца ў выглядзе 5.

6
дададзена

Вам трэба AtomicInteger калі вам трэба прачытаць зменную і запісаць вынік у залежнасці ад лічыцца значэнне . Напрыклад, я ++ чытае я (напрыклад, 3 ) і запісвае я + 1 (напрыклад, 4 ). Паток можа быць перапынены тым, і тры іншыя тэмы инкремент я таксама. Цяпер, калі мы вернемся, я на самой справе мае значэнне 6 але наш паток ўсё яшчэ піша 4 , заснаваны на тым, што ён загадзя прачытаць.

AtomicInteger.getAndIncrement ensures you're not interrupted and therefore always incrementing properly. Moreover, the result is always flushed into memory, whereas a non-volatile i might not be flushed to memory. In this case other threads might not even see the changes.

2
дададзена

Вам трэба AtomicInteger калі вам трэба прачытаць зменную і запісаць вынік у залежнасці ад лічыцца значэнне . Напрыклад, я ++ чытае я (напрыклад, 3 ) і запісвае я + 1 (напрыклад, 4 ). Паток можа быць перапынены тым, і тры іншыя тэмы инкремент я таксама. Цяпер, калі мы вернемся, я на самой справе мае значэнне 6 але наш паток ўсё яшчэ піша 4 , заснаваны на тым, што ён загадзя прачытаць.

AtomicInteger.getAndIncrement ensures you're not interrupted and therefore always incrementing properly. Moreover, the result is always flushed into memory, whereas a non-volatile i might not be flushed to memory. In this case other threads might not even see the changes.

2
дададзена

атамарнага аперацыі патрабуецца, калі вы мутаваць зменную. рабіць Int а = 10; з'яўляецца атамарна аперацыяй, але яе не адзін, які дасць вам гэтую праблему. праблемныя даючы аперацыі звычайна муціруе з іх, як а ++ або а = а + 2; і гэтак далей.

Java Спецыфікацыя гарантуе, што «чытанне» і «лісты» з'яўляюцца атамарнага аперацыі не іх камбінацыі. таму аперацыя, якая счытвае, дадае 1, а затым запісвае вынік назад 'не з'яўляецца атамарна ў адпаведнасці са спецыфікацыяй. такія аперацыі называюцца складаныя аперацыі, і яны, як правіла, павінны быць атамарнага ў кантэксце іх выкарыстання ў кодзе.

Атамныя тыпы дапамагаюць вырашыць гэтую праблему. выкарыстоўваючы incrementAndget() на атамным тыпу робіць «чытае, дадае 1, а затым запісвае вынік назад і чытае новы вынік» адзін атамарна аперацыі ў кантэксце Нітачны.

Спадзяюся, што гэта дапамагае. Дарэчы, вы павінны прачытаць гэта ( Http: //walivi.wordpress.com/2013/08/24/concurrency-in-java-a-beginners-introduction/ ) артыкул аб асновах паралельнасці і ніткамі. гэта тлумачыць такія рэчы прыгожа.

0
дададзена

Я думаю, што гэта азначае, што доўга і двойчы - аперацыя чытання з'яўляецца атамарна і пісаць аперацыя з'яўляецца атамарна. Але чытанне + запіс не з'яўляецца атамарна.

volatile long num;
num = num+1

Вышэй ня струменева. Там чытаць і пісаць дзве асобныя аперацыі. Кожны з іх гарантавана будуць атамарнага, але ўсё выраз не з'яўляецца.

Для таго, каб зрабіць яго струменева вам трэба будзе выкарыстоўваць AtomicLong і выкарыстоўваць функцыю getAndIncrement.

0
дададзена
Ваша першая прапанова ўводзіць у зман без спасылкі на няўстойлівы.
дададзена аўтар assylias, крыніца
Ён кажа прама супрацьлеглае: у доўга; а = 1; , то другое сцвярджэнне не гарантуецца атамарным.
дададзена аўтар assylias, крыніца
не, гэта не робіць - «Аперацыі зменныя тыпу доўгай або двайны толькі атомарных, калі яны аб'яўленыя з лятучым ключавым словам», звярніце ўвагу на лятучым
дададзена аўтар gkamal, крыніца

Я думаю, што гэта азначае, што доўга і двойчы - аперацыя чытання з'яўляецца атамарна і пісаць аперацыя з'яўляецца атамарна. Але чытанне + запіс не з'яўляецца атамарна.

volatile long num;
num = num+1

Вышэй ня струменева. Там чытаць і пісаць дзве асобныя аперацыі. Кожны з іх гарантавана будуць атамарнага, але ўсё выраз не з'яўляецца.

Для таго, каб зрабіць яго струменева вам трэба будзе выкарыстоўваць AtomicLong і выкарыстоўваць функцыю getAndIncrement.

0
дададзена
Ваша першая прапанова ўводзіць у зман без спасылкі на няўстойлівы.
дададзена аўтар assylias, крыніца
Ён кажа прама супрацьлеглае: у доўга; а = 1; , то другое сцвярджэнне не гарантуецца атамарным.
дададзена аўтар assylias, крыніца
не, гэта не робіць - «Аперацыі зменныя тыпу доўгай або двайны толькі атомарных, калі яны аб'яўленыя з лятучым ключавым словам», звярніце ўвагу на лятучым
дададзена аўтар gkamal, крыніца

You use int or long based on the upper/lower limit on the range of numbers you are dealing with. Please do not mix non-atomic behavior of long with AtomicLong. Whatever you have written above is correct but you are probably mixing both concepts. AtomicXXX are more useful in cases where you are doing "compare & set" kind of operations. For example even when int can be modified/read atomically following code will be incorrect in multithreaded environment :

int i =10
..
..
..
if(i == 10) i++;

у шматструменнай асяроддзі два паток можа адкрыць код атамарнага і абноўленае значэнне I і робяць яго прыйсці ва ўзгодненым стане. SO справіцца з такімі сітуацыямі, як правіла, вы захоўваеце код «калі (я == 10) я ++;" з сінхранізаваць блокам. Аднак клас AtomicInteger забяспечвае API для дасягнення такіх рэчаў без выкарыстання сінхранізаваных блокаў, якія больш павольна. Тое ж самае і ў выпадку AtmoicLong API,

0
дададзена

You use int or long based on the upper/lower limit on the range of numbers you are dealing with. Please do not mix non-atomic behavior of long with AtomicLong. Whatever you have written above is correct but you are probably mixing both concepts. AtomicXXX are more useful in cases where you are doing "compare & set" kind of operations. For example even when int can be modified/read atomically following code will be incorrect in multithreaded environment :

int i =10
..
..
..
if(i == 10) i++;

у шматструменнай асяроддзі два паток можа адкрыць код атамарнага і абноўленае значэнне I і робяць яго прыйсці ва ўзгодненым стане. SO справіцца з такімі сітуацыямі, як правіла, вы захоўваеце код «калі (я == 10) я ++;" з сінхранізаваць блокам. Аднак клас AtomicInteger забяспечвае API для дасягнення такіх рэчаў без выкарыстання сінхранізаваных блокаў, якія больш павольна. Тое ж самае і ў выпадку AtmoicLong API,

0
дададзена