Што такі стан гонкі?

Пры напісанні шматструменных прыкладанняў адна з найбольш распаўсюджаных праблем - гэта ўмовы гонкі.

Мае пытанні для супольнасці:

Што такі стан гонкі? Як вы іх выяўляеце? Як вы спраўляецеся з імі? Нарэшце, як вы іх прадухіляеце?

795
29 авг. зададзены bmurphy1976 29 жнів. 2008-08-29 18:55 '08 у 18:55 2008-08-29 18:55
@ 18 адказаў

Ўмова гонкі ўзнікае, калі два ці больш патоку могуць звяртацца да агульных дадзеных, і яны спрабуюць змяніць яго ў адно і тое ж час. Паколькі алгарытм планавання патокаў можа мяняцца паміж патокамі ў любы час, вы не ведаеце парадак, у якім патокі будуць спрабаваць атрымаць доступ да агульных дадзеных. Такім чынам, вынік змены дадзеных залежыць ад алгарытму планавання патоку, то ёсць абодва патоку з'яўляюцца "гоначнымі" для доступу / змены дадзеных.

Часта ўзнікаюць праблемы, калі адзін паток выконвае "check-then-act" (напрыклад, "праверка", калі значэнне X, затым "дзейнічаць", каб рабіць нешта, што залежыць ад значэння X), а іншы паток нешта робіць значэнне паміж "праверкай" і "дзеяннем". напрыклад:

 if (x == 5) // The "Check" { y = x * 2; // The "Act" // If another thread changed x in between "if (x == 5)" and "y = x * 2" above, // y will not be equal to 10. } 

Кропка, y можа быць 10, ці гэта можа быць што заўгодна, у залежнасці ад таго, ці змяніўся іншы паток x паміж праверкай і дзеяннем. У вас няма рэальнага спосабу даведацца.

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

 // Obtain lock for x if (x == 5) { y = x * 2; // Now, nothing can change x until the lock is released. // Therefore y = 10 } // release lock for x released // Obtain lock for x if (x == 5) { y = x * 2; // Now, nothing can change x until the lock is released. // Therefore y = 10 } // release lock for x 
986
29 авг. адказ дадзены Lehane 29 жнів. 2008-08-29 19:05 '08 у 19:05 2008-08-29 19:05

Ўмова "гонкі" існуе, калі шматструменны (ці інакш паралельны) код, які будзе звяртацца да агульнага рэсурсу, можа зрабіць гэта такім чынам, каб выклікаць нечаканыя вынікі.

Возьмем гэты прыклад:

 for ( int i = 0; i < 10000000; i++ ) { //lock x x = x + 1; //unlock x } 

Тут адказ прыходзіць як 50 000 000 кожны раз.

Для атрымання дадатковай інфармацыі аб блакаванні выканайце пошук: мьютекс, семафор, крытычны раздзел, агульны рэсурс.

183
29 авг. адказ дадзены privatehuff 29 жнів. 2008-08-29 20:01 '08 у 20:01 2008-08-29 20:01

Што такі стан гонкі?

Вы плануеце перайсці ў кіно ў 17:00. Вы пытаеце аб наяўнасці білетаў у 16:00. Прадстаўнік кажа, што яны даступныя. Вы паслабляецеся і дабіраецеся да акна білета за 5 хвілін да шоу. Я ўпэўнены, што вы можаце здагадацца, што адбываецца: гэта поўны дом. Праблема тут складалася ў працягласці паміж праверкай і дзеяннем. Вы спыталі 4 і выступілі ў 5. У той жа час нехта яшчэ схапіў квіткі. Гэта ўмова гонкі - у прыватнасці сцэнар "праверкі-дзеянні-дзеянні" умоў гонкі.

Як вы іх выяўляеце?

Рэлігійны агляд кода, шматструменныя модульныя тэсты. Няма цэтліка. На гэтым ёсць убудова Eclipse, але нічога стабільнага пакуль няма.

Як вы апрацоўваеце і прадухіляеце іх?

Лепш за ўсё было б ствараць свабодныя пабочныя эфекты і функцыі без грамадзянства, максімальна выкарыстоўваць нязменлівыя. Але гэта не заўсёды магчыма. Такім чынам, выкарыстоўваючы java.util.concurrent.atomic, дапамогуць паралельныя структуры дадзеных, правільная сінхранізацыя і заснаваны на акцёрах concurrency.

Лепшым рэсурсам для concurrency з'яўляецца JCIP. Вы таксама можаце атрымаць больш падрабязную інфармацыю тут. .

121
05 окт. адказ дадзены Vishal Shukla 05 каст. 2013-10-05 00:20 '13 у 0:20 2013/10/05 00:20

Існуе важнае тэхнічнае адрозненне паміж ўмовамі гонкі і гонкамі дадзеных. Большасць адказаў, падобна, робяць здагадка, што гэтыя тэрміны эквівалентныя, але яны не з'яўляюцца.

Галасаванне дадзеных адбываецца, калі 2 каманды звяртаюцца да аднаго і таго ж месцы памяці, па меншай меры адзін з гэтых зваротаў з'яўляецца запісам, і няма неабходнасці да парадкавання паміж гэтымі зваротамі. Цяпер тое, што адбываецца, адбываецца да замовы, схільна вялікай колькасці дэбатаў, але ў цэлым пары блакавання улоков на адной і той жа зменнай блакавання і пар сігналу чакання пры адной і той жа зменнай ўмовы выклікаюць выпадковы парадак.

Стан гонкі - гэта семантычная памылка. Гэта недахоп, звязаны з сінхранізацыяй або упарадкаваннем падзей, што прыводзіць да памылковага паводзінам праграмы.

Многія ўмовы гонкі могуць (і на самай справе) выкліканыя гонкамі дадзеных, але гэта неабавязкова. На самай справе, расы дадзеных і ўмовы гонкі не з'яўляюцца ні неабходным, ні дастатковай умовай для адзін аднаго. Гэта паведамленне ў блогу таксама тлумачыць розніцу вельмі добра, з простым прыкладам банкаўскіх транзакцый. Вось яшчэ адзін просты прыклад, які тлумачыць розніцу.

Цяпер, калі мы ўжылі тэрміналогію, паспрабуем адказаць на зыходны пытанне.

Улічваючы, што ўмовы гонкі з'яўляюцца семантычным памылкамі, няма агульнага спосабу іх выяўлення. Гэта звязана з тым, што няма спосабу аўтаматызаванага аракула, які можа адрозніць правільнае і няправільнае паводзіны праграмы ў агульным выпадку. Выяўленне гонкі - невырашальная праблема.

З іншага боку, расы дадзеных маюць дакладнае вызначэнне, якое не абавязкова звязана з правільнасцю, і таму іх можна выявіць. Існуе мноства разнавіднасцяў дэтэктараў гонкі дадзеных (статычнае / дынамічнае выяўленне гонкі дадзеных, выяўленне гонкі дадзеных на аснове блакавання, выяўленне на аснове дадзеных на аснове раней выяўленых дадзеных, выяўленне гібрыдных дадзеных). Сучасны дынамічны дэтэктар гонкі дадзеных ThreadSanitizer , які на практыцы працуе вельмі добра.

Апрацоўка разлікаў дадзеных у агульным патрабуе некаторай дысцыпліны праграмавання, каб выклікаць гэта - перад рэбрамі паміж зваротамі да агульных дадзеных (альбо падчас распрацоўкі, альбо пасля іх выяўлення з выкарыстаннем вышэйзгаданых інструментаў). гэта можна зрабіць з дапамогай блокаў зараз, зменных умоў, семафораў і г.д. Аднак можна таксама выкарыстоўваць розныя парадыгмы праграмавання, такія як перадача паведамленняў (замест агульнай памяці), якія прадухіляюць расследаванне дадзеных па пабудове.

54
29 авг. адказ дадзены Baris Kasikci 29 жнів. 2013-08-29 11:45 '13 у 11:45 2013/08/29 11:45

Сортоканоническое вызначэнне: "калі два патокі адначасова звяртаюцца ў адно і тое ж месца ў памяці, і па крайняй меры адзін з іх - гэта запіс". У сітуацыі паток чытача можа атрымаць старое значэнне або новае значэнне, у залежнасці ад таго, які паток "выйграе гонку". Гэта не заўсёды памылка: на самай справе некаторыя сапраўды валасатыя алгарытмы нізкага ўзроўню робяць гэта адмыслова, але гэтага, як правіла, варта пазбягаць. @Steve Gury дае добры прыклад таго, калі гэта можа быць праблемай.

33
29 авг. адказ дадзены Chris Conway 29 жнів. 2008-08-29 19:21 '08 у 19:21 2008-08-29 19:21

Стан гонкі - гэта свайго роду памылка, якая адбываецца толькі з пэўнымі часовымі ўмовамі.

Прыклад: Уявіце, што ў вас ёсць два патокі: A і B.

У струмені A:

 object.a = 0 

Калі паток A выгружаны адразу пасля праверкі таго, што object.a не з'яўляецца нулявым, B будзе рабіць a = 0 , а калі паток A атрымае працэсар, ён будзе "дзяліць на нуль".

Гэтая памылка ўзнікае толькі тады, калі паток A выгружаецца адразу пасля інструкцыі if, гэта вельмі рэдка, але гэта можа адбыцца.

30
29 авг. адказ дадзены Steve Gury 29 жнів. 2008-08-29 19:03 '08 у 19:03 2008-08-29 19:03

Умовы гонкі адбываюцца ў шматструменных прыкладаннях або шматпрацэсарных сістэмах. Ўмова гонкі, ў яго самым базавым, - гэта ўсё, што робіць здагадку, што дзве рэчы не ў адным патоку або працэсе не будуць выконвацца ў вызначаным парадку, не прыкладаючы крокаў для забеспячэння іх выканання. Звычайна гэта адбываецца, калі два патокі перадаюць паведамлення, усталёўваючы і правяраючы зменныя-члены класа, да якіх могуць звяртацца. Амаль заўсёды існуе ўмова гонкі, калі адзін паток выклікае сон, каб даць іншы час для завяршэння задачы (калі гэты сон не знаходзіцца ў цыкле з некаторым механізмам праверкі).

Інструменты для прадухілення умоў гонкі залежаць ад мовы і АС, але некаторыя з іх - гэта мьютексы, крытычныя раздзелы і сігналы. Мьютексы добрыя, калі вы хочаце пераканацца, што вы адзіны, хто нешта робіць. Сігналы добрыя, калі вы хочаце пераканацца, што нехта яшчэ скончыў нешта рабіць. Мінімізацыя агульных рэсурсаў таксама можа дапамагчы прадухіліць нечаканае паводзіны

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

Знак подпісы, што ў аднаго ёсць умова гонкі, ёсць, калі ёсць праблема, якая ўзнікае толькі перыядычна на некаторых машынах. Агульнымі памылкамі былі б збоі і взаимоблокировки. З пратакалявання вы зможаце знайсці пацярпелы раён і вярнуцца адтуль.

18
29 авг. адказ дадзены tsellon 29 жнів. 2008-08-29 19:12 '08 у 19:12 2008-08-29 19:12

Стан гонкі звязана не толькі з праграмным забеспячэннем, але і з апаратным забеспячэннем. На самай справе тэрмін першапачаткова быў прыдуманы апаратнай галіной.

Згодна з вікіпедыі :

Гэты тэрмін звязаны з ідэяй двух сігналаў, якія вядуць адзін да аднаго, каб уплываць на выхад у першую чаргу.

Стан гонкі ў лагічнай схеме:

2019

04 авг. адказ дадзены nybon 04 жнів. 2017-08-04 06:57 '17 у 06:57 2017/08/04 06:57

Microsoft сапраўды апублікавала сапраўды падрабязную артыкул па гэтым пытанні умоў гонкі і тупікоў. Найбольш сумарным з іх будзе абзац загалоўка:

Ўмова гонкі ўзнікае, калі два патокі звяртаюцца да агульнай зменнай пры ў той жа час. Першы паток чытае зменную, а другі thread счытвае адно і тое ж значэнне з зменнай. Затым першая нітка і другая нітка выконвае свае аперацыі над значэннем, і яны ўдзельнічаюць у гонцы каб убачыць, які паток можа запісаць значэнне, апошняе для агульнай зменнай. Значэнне патоку, якое запісвае сваё значэнне last, захоўваецца, таму што паток піша над значэннем, якое папярэдні паток напісаў.

8
14 сент. адказ дадзены Konstantin Dinev 14 сент. 2012-09-14 11:00 '12 аб 11:00 2012/09/14 11:00

Стан гонкі - гэта сітуацыя на паралельным праграмаванні, дзе два паралельных патоку або працэсаў і выніковае канчатковае стан залежаць ад таго, хто першым атрымлівае рэсурс.

5
29 авг. адказ дадзены Jorge Córdoba 29 жнів. 2008-08-29 19:07 '08 у 19:07 2008-08-29 19:07

Добра, гэта 4 пытанні. адзін за адным адказ, як пад ....

Што такі стан гонкі?

Гэта адбываецца, калі выснова і / або вынік працэсу крытычна залежаць ад паслядоўнасці або часу іншых падзей, г.зн. 2 сігналы ганяюцца, каб спачатку змяніць выхад.

Як вы іх выяўляеце?

Гэта прыводзіць да памылкі, якую цяжка лакалізаваць.

Як вы спраўляецеся з імі?

выкарыстанне семафораў

І нарэшце,

Як вы іх прадухіляеце?

Адзін са спосабаў пазбегнуць стану гонкі - выкарыстоўваць механізм блакавання рэсурсаў. але блакавальныя рэсурсы могуць прывесці да взаимоблокировкам. які павінен быць разгледжаны.

2
14 нояб. адказ дадзены Adnan Qureshi 14 лістапада. 2014-11-14 16:43 '14 у 16:43 2014/11/14 16:43

Ўмова гонкі з'яўляецца непажаданай сітуацыяй, калі прылада або сістэма спрабуюць выканаць дзве або больш аперацыі адначасова, але з-за характару прылады або сістэмы аперацыі павінны выконвацца ў правільнай паслядоўнасці ў каб зрабіць гэта правільна.

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

2
13 апр. адказ дадзены dilbag koundal 13 крас. 2012-04-13 14:29 '12 у 14:29 2012-04-13 14:29

Вось класічны прыклад балансу банкаўскага рахунку, які дапаможа пачаткоўцам зразумець патокі ў Java лёгка wrt ўмовы гонкі:

2
22 нояб. адказ дадзены realPK 22 лістапада. 2011-11-22 08:35 '11 у 08:35 2011-11-22 08:35

Ўмова гонкі з'яўляецца непажаданай сітуацыяй, якая ўзнікае, калі два ці больш працэсу могуць адначасова атрымліваць доступ і змяняць сумесна выкарыстоўваюцца дадзеныя. Гэта адбылося з-за канфлікту доступу да рэсурсу. Праблема крытычнага перасеку можа прывесці да стану гонкі. Для вырашэння крытычнага стану працэсу мы вымаем толькі адзін працэс за раз, які выконвае крытычны падзел.

0
05 дек. адказ дадзены rashedcs 05 снеж. 2018-12-05 09:55 '18 у 09:55 2018/12/05 09:55

Паспрабуйце гэты базавы прыклад для лепшага разумення стану гонкі:

  public class ThreadRaceCondition {  public static void main(String[] args) throws InterruptedException { Account myAccount = new Account(22222222); // Expected deposit: 250 for (int i = 0; i < 50; i++) { Transaction t = new Transaction(myAccount, Transaction.TransactionType.DEPOSIT, 5.00); t.start(); } // Expected withdrawal: 50 for (int i = 0; i < 50; i++) { Transaction t = new Transaction(myAccount, Transaction.TransactionType.WITHDRAW, 1.00); t.start(); } // Temporary sleep to ensure all threads are completed. Don't use in // realworld :-) Thread.sleep(1000); // Expected account balance is 200 System.out.println("Final Account Balance: " + myAccount.getAccountBalance()); } } class Transaction extends Thread { public static enum TransactionType { DEPOSIT(1), WITHDRAW(2); private int value; private TransactionType(int value) { this.value = value; } public int getValue() { return value; } }; private TransactionType transactionType; private Account account; private double amount;  public Transaction(Account account, TransactionType transactionType, double amount) { this.transactionType = transactionType; this.account = account; this.amount = amount; } public void run() { switch (this.transactionType) { case DEPOSIT: deposit(); printBalance(); break; case WITHDRAW: withdraw(); printBalance(); break; default: System.out.println("NOT A VALID TRANSACTION"); } ; } public void deposit() { this.account.deposit(this.amount); } public void withdraw() { this.account.withdraw(amount); } public void printBalance() { System.out.println(Thread.currentThread().getName() + " : TransactionType: " + this.transactionType + ", Amount: " + this.amount); System.out.println("Account Balance: " + this.account.getAccountBalance()); } } class Account { private int accountNumber; private double accountBalance; public int getAccountNumber() { return accountNumber; } public double getAccountBalance() { return accountBalance; } public Account(int accountNumber) { this.accountNumber = accountNumber; } // If this method is not synchronized, you will see race condition on // Remove syncronized keyword to see race condition public synchronized boolean deposit(double amount) { if (amount < 0) { return false; } else { accountBalance = accountBalance + amount; return true; } } // If this method is not synchronized, you will see race condition on // Remove syncronized keyword to see race condition public synchronized boolean withdraw(double amount) { if (amount > accountBalance) { return false; } else { accountBalance = accountBalance - amount; return true; } } } 
0
31 мая '13 в 18:51 2013-05-31 18:51 адказ дадзены Morsu 31 мая '13 у 18:51 2013/05/31 18:51

Вы можаце прадухіліць стан гонкі, калі карыстаецеся класы "Atomic". Прычына ў тым, што струмень не падзяляе аперацыі get і set, прыклад ніжэй:

 AtomicInteger ai = new AtomicInteger(2); ai.getAndAdd(5); 

У выніку ў вас будзе 7 у спасылцы "ai". Хоць вы зрабілі два дзеянні, але абедзве аперацыі пацвярджаюць той жа паток, і ні адзін іншы струмень не будзе ўмешвацца ў гэта, гэта азначае адсутнасць умоў гонкі!

0
12 авг. адказ дадзены Aleksei Moshkov 12 жнів. 2017-08-12 17:48 '17 у 17:48 2017/08/12 17:48

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

Аднак, выкарыстоўваючы інструмент для выяўлення стану гонкі, ён будзе заўважаны як небяспечнае стан гонкі.

Падрабязней пра стан гонкі тут, http://msdn.microsoft.com/en-us/magazine/cc546569.aspx .

0
07 сент. адказ дадзены octoback 07 сент. 2014-09-07 12:11 '14 у 12:11 2014/09/07 00:11

Разгледзім аперацыю, якая павінна адлюстроўваць кошт, як толькі кошт будзе павялічаны. г.зн., як толькі CounterThread павялічвае значэнне DisplayThread, неабходна адлюстраваць апошняе абноўленае значэнне.

 int i = 0; 

выхад

 CounterThread -> i = 1 DisplayThread -> i = 1 CounterThread -> i = 2 CounterThread -> i = 3 CounterThread -> i = 4 DisplayThread -> i = 4 

Тут CounterThread часта блакуе блакаванне і абнаўляе значэнне да таго, як яго адлюструе DisplayThread. Тут існуе ўмова Расы. Стан гонкі можна вырашыць, выкарыстоўваючы Synchronzation

0
15 июля '15 в 11:00 2015-07-15 11:00 адказ дадзены bharanitharan 15 ліпеня '15 аб 11:00 2015/07/15 11:00

Другие вопросы по меткам или Задайте вопрос