0
Ìíîãîïîòî÷íîå ïðîãðàììèðîâàíèå è Java
Êîððåêòíîñòü, ïàòòåðíû, ïîäõîäû
Åâãåíèé Êèðïè÷¼â
18 àïðåëÿ 2010 ã.
Îáñóæäåíèå:
http:...
Öåëü äîêëàäà
Ðàñøèðèòü êðóãîçîð â îáëàñòè ìíîãîïîòî÷íîãî
ïðîãðàììèðîâàíèÿ âîîáùå è íà Java â ÷àñòíîñòè.
Êîððåêòíîñòü
Êàê ñ...
Êëàññèôèêàöèÿ ìíîãîïîòî÷íûõ ïðîãðàìì
Parallelism vs Concurrency
Parallel Îäíà çàäà÷à áüåòñÿ íà ìíîãî ÷àñòåé
Concurrent Ìíî...
Ïðîáëåìû ìíîãîïîòî÷íîãî ïðîãðàììèðîâàíèÿ
Ïèñàòü concurrent ïðîãðàììû  òðóäíî.
Îáû÷íî ñëàáàÿ ïîääåðæêà ñî ñòîðîíû ÿçûêà
Òðó...
Êëàññèôèêàöèÿ ìíîãîïîòî÷íûõ ïðîãðàìì (contd.)
Ïðîãðàììû áûâàþò ðàçíûå.
Raytracer Server IDE
Ñêîëüêî çàäà÷? Ìíîãî Ìíîãî Ìàë...
×àñòü 1. Êîððåêòíîñòü.
Ñîäåðæàíèå
Êîððåêòíîñòü
Ïðè÷èíû áàãîâ
Äîêàçàòåëüñòâî êîððåêòíîñòè
Óëó÷øåíèå êîððåêòíîñòè
Ïàòòåðíû è ïîäõîäû
Ïàðàëëåëèçì
Co...
Ïðè÷èíû áàãîâ
Êîðåíü âñåõ çîë  èçìåíÿåìîå âî âðåìåíè ñîñòîÿíèå.
N íèòåé, K ñîñòîÿíèé ⇒ O(KN) ïåðåïëåòåíèé
Ïðîìåæóòî÷íûå ñî...
Ïðè÷èíû áàãîâ
Sequentialy correct + Sequentially correct =
Concurrently correct
Äîêàçóåìàÿ êîððåêòíîñòü
Face it:
Ëèáî ïðîãðàììà äîêàçóåìî êîððåêòíà
Ëèáî îíà, ïî÷òè íàâåðíÿêà, íåêîððåêòíà
Ïóñòü âåðîÿòíîñ...
Äîêàçóåìàÿ êîððåêòíîñòü
Face it:
Ëèáî ïðîãðàììà äîêàçóåìî êîððåêòíà
Ëèáî îíà, ïî÷òè íàâåðíÿêà, íåêîððåêòíà
Tony Hoare:
The...
Ôîðìàëüíûå ìåòîäû
Ïðèìåíÿòü íå îáÿçàòåëüíî.
Ôîðìàëüíûå ìåòîäû
À çà÷åì òîãäà îíè âîîáùå íóæíû?
×òîáû îïèñûâàòü ñèñòåìó ïîëóôîðìàëüíî
×òîáû ÷óÿòü: ôîðìàëèçóåìà ëè ñèñòå...
Ôîðìàëüíûå ìåòîäû
Ìîé îïûò: äîñòàòî÷íî ïîïûòàòüñÿ ôîðìàëèçîâàòü ñèñòåìó:
Âñïëûâàþò ïðîòèâîðå÷èÿ, íåäîãîâîðêè â òðåáîâàíèÿõ...
Ôîðìàëüíûå ìåòîäû
×òî æå ýòî çà ìåòîäû?
Íàïðèìåð, ëèíåéíàÿ òåìïîðàëüíàÿ ëîãèêà.
Äîêàçóåìàÿ êîððåêòíîñòü
Ëèíåéíàÿ òåìïîðàëüíàÿ ëîãèêà  ñïîñîá ðàññóæäàòü î
ïîñëåäîâàòåëüíîñòÿõ ñîáûòèé.
Ïðîãðàììà ìîäåëèðóå...
Ñòðóêòóðà Êðèïêå
Ñòðóêòóðà Êðèïêå ≈ ãðàô ñîñòîÿíèé.
Ìíîæåñòâî ñîñòîÿíèé
Íåêîòîðûå íà÷àëüíûå
Íåêîòîðûå ñîåäèíåíû ïåðåõîäîì
...
Ñòðóêòóðà Êðèïêå
Ìèêðîâîëíîâêà.
Ñòðóêòóðà Êðèïêå
Ïåðåõîäû íå ïîäïèñàíû, ïîòîìó ÷òî:
Íîìåð ñîñòîÿíèÿ ïîëíîñòüþ îïèñûâàåò ñîñòîÿíèå
ïðîãðàììû
Åñëè ïåðåõîä ó...
LTL
Ëèíåéíàÿ òåìïîðàëüíàÿ ëîãèêà (Linear Temporal Logic).
Ðàññóæäàåò î ïîñëåäîâàòåëüíîñòÿõ ñîñòîÿíèé ìèðà âî âðåìåíè.
Åñòü...
Ôîðìóëû LTL
p1, p2, . . . Ïåðåìåííûå
A ∧ B, ¬A. . . Ëîãè÷åñêèå ñâÿçêè
XA Â ñëåäóþùèé ìîìåíò A (neXt)
GA ≡ A Âñåãäà A (Glob...
Áåñêîíå÷íîñòè
Íà÷èíàÿ ñ íåêîòîðîãî ìîìåíòà, íàâñåãäà: FG A ≡ ♦ A
Áåñêîíå÷íî ÷àñòî: GF A ≡ ♦A
Èëëþñòðàöèÿ ôîðìóë LTL
Ñâîéñòâà
Æèâîñòü (liveness)
×òîEòî õîðîøåå êîãäàEíèáóäü ïðîèçîéäåòX ♦Alive
Çàäàíèå êîãäàEíèáóäü íà÷íåòñÿ
Áåçîïàñíîñòü (saf...
Ñâîéñòâà
Ñïðàâåäëèâîñòü (fairness)
Òî, ÷òî ìîæåò ïðîèçîéòè  ïðîèçîéäåò
Ñëàáàÿ: ♦ Req → ♦Ack
Ðåñóðñ çàïðîøåí @è îñòàåòñÿ çà...
Ïðèìåðû LTL-ñâîéñòâ
Óñòðîéñòâî íå âûêëþ÷àåòñÿ ñàìî ïî ñåáå
(isOn → (isOn U (turnOPressed ∨ noBattery))
Íå ðåæå ÷åì ðàç â 5...
Model checking
Íàóêà î ïðîâåðêå ñâîéñòâ ïðîãðàìì (íàïðèìåð, LTL) íà îñíîâå
èõ ìîäåëåé (íàïðèìåð, ñòðóêòóð Êðèïêå)  Model c...
Èíñòðóìåíò: SPIN
Ïîâñåìåñòíî èñïîëüçóåìûé ÿçûê + âåðèôèêàòîð LTL-ñâîéñòâ
äëÿ ìíîãîçàäà÷íûõ ñèñòåì.
Ëàóðåàò ACM Software Sy...
AspectJ+LTL
http://www.sable.mcgill.ca/~ebodde/rv/JLO/  tEvyX ïðîâåðÿåò
v„vEñâîéñòâà â ðàíòàéìå @çàáðîøåíAF
http://abc.com...
Model checking:further reading
http://www.inf.unibz.it/~artale/FM/slide3.pdf
Òóòîðèàë ïî v„vF
http:
//citeseerx.ist.psu.ed...
Áëèæå ê äåëó
Êàê ðàññóæäàòü î ðåàëüíûõ ïðîãðàììàõ?
Àêñèîìàòèêà: Java memory model è ò.ï.
Îñíîâíûå ïàðàìåòðû (äîêóìåíòèðóéò...
Java Memory Model
Ñ íåé íåîáõîäèìî îçíàêîìèòüñÿ. Ìíîãî ñþðïðèçîâ.
Íåëüçÿ ñîçäàâàòü íèòè â êîíñòðóêòîðå
Íå-nal ïîëÿ íå ïîòî...
Thread safety
Immutable. Ó îáúåêòà âñåãî 1 ñîñòîÿíèå.
Thread-safe. Êàæäàÿ îïåðàöèÿ ñàìà ïî ñåáå
áåçîïàñíà/àòîìàðíà. Ïîñëåä...
Thread safety
Thread-compatible. Ìîæíî èñïîëüçîâàòü ìíîãîïîòî÷íî,
åñëè íå âûçûâàòü îïåðàöèè îäíîâðåìåííî.
Íóæíà âíåøíÿÿ ñè...
CheckThread
Íàáîð àííîòàöèé äëÿ äîêóìåíòèðîâàíèÿ thread safety.
Åñòü ïëàãèí ê IDEA.
Î÷åíü ïîëåçíî.
Ïðèìåð
@ThreadSafe clas...
Java Path Finder
Âèðòóàëüíàÿ ìàøèíà, óìåþùàÿ ñèìâîëüíî âûïîëíÿòü Java-êîä
è âåðèôèöèðîâàòü ñâîéñòâà äëÿ âñåõ âîçìîæíûõ çàï...
Äðóãèå òóëû
Ñòàòè÷åñêèé àíàëèç ìíîãîïîòî÷íûõ îøèáîê åñòü è â:
PMD
FindBugs (åñòü ïëàãèí ê IDEA)
Ïðîâåðåíî: ïîìîãàåò (è íå ...
Ôèëîñîôñêîå èçáàâëåíèå îò áàãîâ
Íàäî óìåíüøèòü O(KN).
Óìåíüøèòü ÷èñëî íàáëþäàåìûõ ñîñòîÿíèé (K)
smmut—˜ility
Èíêàïñóëÿöèÿ ...
Immutability
Íåëüçÿ èçìåíèòü âîîáùå ⇒ íåëüçÿ èçìåíèòü íåïðàâèëüíî, íå â
òîì ïîðÿäêå . . .
Âñå ïîëÿ private, nal, è èõ êëàñ...
Immutability
Íåëüçÿ èçìåíèòü âîîáùå ⇒ íåëüçÿ èçìåíèòü íåïðàâèëüíî, íå â
òîì ïîðÿäêå . . .
Âñå ïîëÿ private, nal, è èõ êëàñ...
Immutability
Íåëüçÿ èçìåíèòü âîîáùå ⇒ íåëüçÿ èçìåíèòü íåïðàâèëüíî, íå â
òîì ïîðÿäêå . . .
Âñå ïîëÿ private, nal, è èõ êëàñ...
Immutability
Íåëüçÿ èçìåíèòü âîîáùå ⇒ íåëüçÿ èçìåíèòü íåïðàâèëüíî, íå â
òîì ïîðÿäêå . . .
Âñå ïîëÿ private, nal, è èõ êëàñ...
Immutability
Íåëüçÿ èçìåíèòü âîîáùå ⇒ íåëüçÿ èçìåíèòü íåïðàâèëüíî, íå â
òîì ïîðÿäêå . . .
Âñå ïîëÿ private, nal, è èõ êëàñ...
Èíêàïñóëÿöèÿ ñîñòîÿíèÿ
Ïðîãðàììà êîððåêòíà ðîâíî íàñòîëüêî, íàñêîëüêî êîððåêòíû è
ñêîîðäèíèðîâàíû âñå, êòî ìîãóò ïîâëèÿòü ...
Âûñîêîóðîâíåâûå îïåðàöèè
Îïðåäåëåíèå: Âûñîêîóðîâíåâàÿ îïåðàöèÿ  îïåðàöèÿ, íå
íàðóøàþùàÿ öåëîñòíîñòü ñèñòåìû.
AtomicInteger...
Âûñîêîóðîâíåâûå îïåðàöèè
×àñòíûé ñëó÷àé:
Ó îáúåêòà â ìåðó áîëüøîå ñîñòîÿíèå
Õî÷åòñÿ àòîìàðíî ïîìåíÿòü íåñêîëüêî åãî ÷àñòåé...
Ôàêòîðèçàöèÿ
Ïðîãðàììà êîððåêòíà ðîâíî íàñòîëüêî, íàñêîëüêî êîððåêòíû è
ñêîîðäèíèðîâàíû âñå, êòî ìîãóò ïîâëèÿòü íà ñîñòîÿí...
Ôàêòîðèçàöèÿ
class DataLoader {
ClientToken beginLoad(Client client);
void writeData(ClientToken token, Data data);
void c...
Ôàêòîðèçàöèÿ
Ñëîæíûé êîä:
Òàáëèöà ClientToken/òðàíçàêöèÿ
(ìíîãîïîòî÷íûå êëèåíòû)
synchronized(locks.get(token))
Ôàêòîðèçàöèÿ
Ðàçîðâåì ëèøíþþ çàâèñèìîñòü ìåæäó íåçàâèñèìûìè
çàäà÷àìè.
class DataLoader {
PerClientLoader beginLoad(Client ...
Ôàêòîðèçàöèÿ
Ïðîñòîé è íåçàãðÿçíåííûé êîä
Ñèíõðîíèçàöèÿ ïðîñòûì synchronized
Íèêàêèõ òàáëèö
Íèêàêèõ ïðîáëåì ñ îõðàíîé òàáë...
Ñèíõðîíèçàöèÿ (ñåðèàëèçàöèÿ äîñòóïà)
Ýòî âñå çíàþò: Õî÷åøü çàùèòèòü îáúåêò  ñäåëàé íà íåì
synchronized.
Ñèíõðîíèçàöèÿ (ñåðèàëèçàöèÿ äîñòóïà)
Åñëè íàäî çàùèòèòü äîñòóï ê êîìáèíàöèè îáúåêòîâ  íàäî
ñèíõðîíèçèðîâàòüñÿ â îäèíàêîâîì...
Áîðüáà ñ äåäëîêàìè
Íóæåí ãëîáàëüíî ôèêñèðîâàííûé ïîðÿäîê áëîêèðîâîê.
Ýêçîòè÷åñêèé ñëó÷àé:
Òàê äåëàòü íå íàäî
void transfer...
Áîðüáà ñ äåäëîêàìè: Ýêçîòè÷åñêèé ñëó÷àé
Íóæåí ãëîáàëüíî ôèêñèðîâàííûé ïîðÿäîê áëîêèðîâîê.
Íàäî äåëàòü âîò òàê
void transfe...
Åùå íåìíîãî î äåäëîêàõ
Íå ñòîèò âûçûâàòü ÷óæèå ìåòîäû (callbacks), äåðæà
áëîêèðîâêó (alien call). Òàêèå âûçîâû ëó÷øå ïðåâð...
Åùå íåìíîãî î äåäëîêàõ
×àñòàÿ ïðè÷èíà äåäëîêîâ  ðåñóðñû è ïóëû.
Äîñòóï ê ðåñóðñàì íàäî óïîðÿäî÷èâàòü, êàê è áëîêèðîâêè
Ïóë...
Ñèíõðîíèçàöèÿ è íàñëåäîâàíèå
Î÷åíü òðóäíî ñäåëàòü ýôôåêòèâíûé thread-safe êëàññ íà îñíîâå
non-thread-safe áàçîâîãî.
Ïðèäåò...
Ñèíõðîíèçàöèÿ è íàñëåäîâàíèå
Ïàòòåðí Thread-safe interface:
Ïîäåëèòå ìåòîäû êîìïîíåíòà íà 2 ÷àñòè
(n—l èíòåðôåéñ C ðåàëèçà...
Èäåìïîòåíòíûå îïåðàöèè
foo();foo(); ∼ foo();
Òîãäà ìîæíî íå çàáîòèòüñÿ îá îãðàíè÷åíèè ÷èñëà âûçîâîâ
foo() (íî foo() äîëæíà...
Èäåìïîòåíòíûå îïåðàöèè
set.add(x)  èäåìïîòåíòíà
x.setFoo(foo)  èäåìïîòåíòíà
list.add(x)  íå èäåìïîòåíòíà
/buy.php?product_...
Èäåìïîòåíòíûå îïåðàöèè
Ïðèìåð äîñòèæåíèÿ èäåìïîòåíòíîñòè:
Ïðèñâîèòü êàæäîìó âûçîâó îïåðàöèè óíèêàëüíûé id
Åñëè òàêîé id óæ...
Îñëàáëåíèå òðåáîâàíèé
Èíîãäà îáåñïå÷èòü æåñòêèå èíâàðèàíòû öåëîñòíîñòè
íåâîçìîæíî.
Îíè ìîãóò íàðóøàòüñÿ èçâíå
Åñòü âíåøíèå...
Îòðèöàòåëüíàÿ îáðàòíàÿ ñâÿçü
Ñóäÿ ïî âñåìó, îäèí èç ìîùíåéøèõ ïðèåìîâ ïðîåêòèðîâàíèÿ
íåêîòîðûõ êëàññîâ ìíîãîçàäà÷íûõ ñèñòå...
Îòðèöàòåëüíàÿ îáðàòíàÿ ñâÿçü
Ïðèìåð ñòðóêòóðû:
Ñèñòåìà ïåðèîäè÷åñêè ïðîñûïàåòñÿ è îñìàòðèâàåòñÿ
Âû÷èñëÿåò, ÷åì ìèð îòëè÷àå...
Îòðèöàòåëüíàÿ îáðàòíàÿ ñâÿçü
Ïëþñû ïîäõîäà
”
ñèñòåìà êàê ñõîäÿùèéñÿ ïðîöåññ“:
Îòðèöàòåëüíàÿ îáðàòíàÿ ñâÿçü
Ïîñëåäñòâèÿ áîë...
Îòðèöàòåëüíàÿ îáðàòíàÿ ñâÿçü
Âûñîêàÿ óñòîé÷èâîñòü
Ñèñòåìà íåóÿçâèìà äëÿ
”
ñìåðòåëüíûõ“ áàãîâ @™orrupted
ñèíãëòîíûD óòå÷êè ...
Îòðèöàòåëüíàÿ îáðàòíàÿ ñâÿçü
Ïðèìåíèìîñòü:
Dataow-like çàäà÷è (äàííûå òåêóò ïî ñèñòåìå ñ ðÿäîì
ýòàïîâ îáðàáîòêè)
Ðåïëèêàöè...
Eventual consistency
Îòíîñèòñÿ ê ðàñïðîñòðàíåíèþ äàííûõ è èçìåíåíèé ïî
ðàñïðåäåëåííîé ñèñòåìå.
”
Êàæäîå èçìåíåíèå êîãäà-íè...
Eventual consistency
Consistency, Availability, Partition Tolerance.
ACID
1 → BASE
2
ACID
Atomicity
Consistency
Isolation
...
Further reading
http://www.webperformancematters.com/journal/2007/8/
21/asynchronous-architectures-4.html  î
ìàñøòàáèðîâàí...
Àáñòðàãèðîâàíèå
Ìíîãîïîòî÷íóþ ïðîãðàììó íàìíîãî ëåã÷å íàïèñàòü è îòëàäèòü,
åñëè â íåé íåò íè÷åãî, êðîìå ñàìîé ñóòè.
Áàãè â...
Àáñòðàãèðîâàíèå
À êàêèå øòóêè óæå åñòü?
Îá ýòîì  ïîçæå.
Àáñòðàãèðîâàíèå: ïðèìåð
Ïðèâÿçêà ê âíåøíåé ñèñòåìå ñêà÷èâàíèÿ óðëîâ.
Çàäàíèÿ ïèøóòñÿ â ôàéëû
Âíåøíÿÿ ñèñòåìà èõ ïîäõâàòûâà...
Àáñòðàãèðîâàíèå: ïðèìåð
Devil in the details:
Íå çàôëóäèòü ñèñòåìó (áëîêèðîâàòüñÿ, åñëè ìíîãî çàäàíèé
”
â ïîëåòå“)
Ñëåäèòü...
Àáñòðàãèðîâàíèå: ïðèìåð
Áûëî: Íåòåñòèðóåìàÿ êàøà, äåëàþùàÿ âñå ñðàçó.
Àáñòðàãèðîâàíèå: ïðèìåð
Ñòàëî:
Ñåìàôîð äëÿ îãðàíè÷åíèÿ ÷èñëà çàäàíèé
”
â ïîëåòå“
Àáñòðàêòíûé ïàòòåðí
”
Stoppable“
Àáñòðàêò...
Àáñòðàãèðîâàíèå: ïðèìåð
interface Stoppable {
void stopSynchronously() throws InterruptedException;
void stopEventually();...
Àáñòðàãèðîâàíèå: ïðèìåð
class BatcherT {
Batcher(int periodMs);
Stoppable start();
abstract void flush(T[] ts);
void submi...
Àáñòðàãèðîâàíèå: ïðèìåð
class PollerT {
Poller(int periodMs);
Stoppable start();
abstract @Nullable T poll();
abstract voi...
Àáñòðàãèðîâàíèå: ïðèìåð
class TimeouterT {
Poller(int periodMs);
Stoppable start();
void submit(T t, int timeoutMs);
abstr...
Àáñòðàãèðîâàíèå: ïðèìåð
Èòîã: Èç áèçíåñ-ëîãèêè ïîëíîñòüþ ïðîïàë ìíîãîïîòî÷íûé êîä.
×àñòü 2. Ïàòòåðíû è ïîäõîäû.
Ñîäåðæàíèå
Êîððåêòíîñòü
Ïðè÷èíû áàãîâ
Äîêàçàòåëüñòâî êîððåêòíîñòè
Óëó÷øåíèå êîððåêòíîñòè
Ïàòòåðíû è ïîäõîäû
Ïàðàëëåëèçì
Co...
Ìîäåëè ìíîãîïîòî÷íûõ âû÷èñëåíèé
Ïàðàëëåëèçì:
MapReduce: Îãðîìíûå îáúåìû äàííûõ, ðàñïðåäåëåííàÿ
îáðàáîòêà
Fork/Join: Çàäà÷è...
MapReduce
Ñëèøêîì èçâåñòíî, ÷òîáû íà íåì îñòàíàâëèâàòüñÿ
Ðåàëèçàöèÿ äëÿ Java: Hadoop
Fork/Join
if(isSmall(problem)) {
return solveSequentially(problem);
} else {
// Fork
ListProblem subproblems = split(probl...
Fork/Join
Ïðèìåð: Øàõìàòû. Ïðåäïðîñìîòð íà n øàãîâ.
n==0 ⇒ îöåíèòü ïîçèöèþ
Fork: Ïî ïîäçàäà÷å íà êàæäûé õîä
Join: Âûáðàòü ...
Fork/Join
Ïðèìåð: Èíòåãðèðîâàíèå.
Èíòåðâàë ìàë ⇒ ïðîèíòåãðèðîâàòü âëîá
Fork: ïî ïîäçàäà÷å íà îáå ïîëîâèíû èíòåðâàëà
Join: ...
Fork/Join
Ïðèìåð: Óìíîæåíèå ìàòðèö: C+ = AB (Â ò.÷. ïîèñê ïóòåé â
ãðàôàõ è ò.ï.)
A è B ìàëû ⇒ âëîá
Fork: Ïîäåëèòü A íà âåð...
Fork/Join
Fork/Join in JDK7
Ïðèìåðíî òàê. Îôèöèàëüíîãî îêîí÷àòåëüíîãî Javadoc äî ñèõ
ïîð íåò.
class Solver extends RecursiveAction {...
Âåêòîðíûå àëãîðèòìû
Huge-scale SIMD: Ïðèìèòèâíûå îïåðàöèè îïåðèðóþò ñðàçó íàä
áîëüøèìè ìàññèâàìè.
Map: Ïðèìåíåíèå ôóíêöèè ...
Âåêòîðíûå ìîäåëè
Ïðåëåñòè:
Ñâåðòêà ïàðàëëåëèçóåòñÿ: Óñêîðåíèå O(P/log P) íà P
ïðîöåññîðàõ (â log P ðàç õóæå ëèíåéíîãî)
Ïðî...
Ïðåôèêñíûå ñóììû
×òî ìîæíî ñäåëàòü ñâåðòêîé/ïðîáåãîì (ò.å. ïàðàëëåëüíî):
sum,min,max,avg,. . .
Radix sort, Quicksort
Ñëîæå...
Ïðåôèêñíûå ñóììû
Îñîáåííî èíòåðåñíî, êàê ýòî äåëàåòñÿ. Áàçîâûå îïåðàöèè
ïîâåðõ ïðîáåãà:
Ðåêóððåíòíàÿ ïîñëåäîâàòåëüíîñòü 1ã...
Ïðåôèêñíûå ñóììû
Óïàêîâêà ìàññèâà (pack, lter).
Ïðåôèêñíûå ñóììû
Ñîðòèðîâêà ïî 1-áèòíîìó ôëàãó (ðàçáèåíèå, partition).
Radixsort òðèâèàëåí.
Ïðåôèêñíûå ñóììû
Ñåãìåíòèðîâàííûé ïðîáåã (Segmented scan).
Ïîçâîëÿåò ðåàëèçîâàòü ðåêóðñèþ áåç ðåêóðñèè.
Ïðåôèêñíûå ñóììû
 öåëîì  êðàñèâûé, ìîùíûé, ïðîñòîé â ðåàëèçàöèè è
íåîáû÷íûé âåêòîðíûé ÿçûê.
×àñòî èñïîëüçóþò íà GPU.
http...
ParallelArray
New in JDK7. Ðåàëèçàöèÿ íåêîòîðûõ âåêòîðíûõ ïðèìèòèâîâ
ïîâåðõ Fork/Join framework.
Ñòàíäàðòíûå: Map, Zip, Fi...
ParallelArray
Ïðèìåð÷èê.
ParallelArrayStudent students = new ParallelArrayStudent(fjPool, data);
double bestGpa = students...
Message-passing concurrency
Ôàêòè÷åñêè åäèíñòâåííûé ïîäõîä â ðàñïðåäåëåííûõ ñèñòåìàõ.
Âîîáùå íåò ðàçäåëÿåìîãî ñîñòîÿíèÿ
Àê...
Message-passing concurrency
Íå ïàíàöåÿ: äåäëîêè åñòü (íî äðóãèå)
Òåì íå ìåíåå, íàïèñàòü êîððåêòíóþ ïðîãðàììó  ïðîùå
Åñòü ô...
Message-passing concurrency
Ðåàëèçàöèè:
Êó÷à ÿçûêîâ: MPI
Termite Scheme
Clojure: agents
Î÷åíü èíòåðåñíàÿ è ìîùíàÿ âàðèàöèÿ...
Message-passing concurrency
Kilim:
Ëåãêîâåñíûå íèòè (1ìëí â ïîðÿäêå âåùåé, ñâåðõáûñòðîå
ïåðåêëþ÷åíèå)
Î÷åíü áûñòðûé messag...
Message-passing concurrency
Further reading:
http://kilim.malhar.net/
http://www.cl.cam.ac.uk/research/srg/opera/publicati...
Event loop
Âàðèàöèÿ íà òåìó message passing, íî  íå ìíîãî
âçàèìîäåéñòâóþùèõ àêòîðîâ, à îäèí (èëè íåñêîëüêî
îäèíàêîâûõ) æèð...
Event loop
private BlockingQueueOurEvent events =
new LinkedBlockingQueueOurEvent();
void mainLoop() {
while(true) {
proce...
Software Transactional Memory
Òðàíçàêöèè íà óðîâíå ïàìÿòè; àòîìàðíûå êóñêè êîäà.
Ïîëíîöåííûé commit/rollback, ïîëíàÿ àòîìà...
Software Transactional Memory
Ïñåâäîêîä:
// Insert a node into a doubly-linked list atomically
atomic {
newNode-prev = nod...
Software Transactional Memory
Ïñåâäîêîä (âïåðâûå ïðåäëîæåíî â ðåàëèçàöèè â Haskell):
atomic {
if (queueSize  0) {
remove i...
Software Transactional Memory
Ðåàëèçàöèè:
Haskell: ïîëíîöåííàÿ è áåçîïàñíàÿ ïîääåðæêà
Clojure: ïîëíîöåííàÿ è íåáåçîïàñíàÿ ...
Software Transactional Memory
Further reading:
http://research.microsoft.com/Users/simonpj/papers/stm/
stm.pdf  gompos—˜le...
Àñèíõðîííîå ïðîãðàììèðîâàíèå
Íàáèðàåò îáîðîòû áëàãîäàðÿ âåáó (AJAX) è áîëüøèì
ðàñïðåäåëåííûì ñèñòåìàì, ãäå ñèíõðîííûé RPC ...
Àñèíõðîííîå ïðîãðàììèðîâàíèå
Ñèíõðîííûé API:
interface API {
Answer compute(Question request) throws Whoops;
}
Àñèíõðîííûé...
Àñèíõðîííîå ïðîãðàììèðîâàíèå
Ïðè÷èíû:
Áëîêèðóþùèå âûçîâû íåóäîáíû èëè íå ïîääåðæèâàþòñÿ
eteˆ
q…s @
”
àñèíõðîííî ïîëó÷èòü ð...
Àñèíõðîííîå ïðîãðàììèðîâàíèå
Ïðîáëåìû:
Íåëèíåéíûé ïîòîê èñïîëíåíèÿ
Î÷åíü íåóäîáíî îòëàæèâàòü
Ïîøàãîâîå âûïîëíåíèå â îòëàä÷...
Àñèíõðîííîå ïðîãðàììèðîâàíèå
public void requestInit() {
AdminConsoleService.App.getInstance().getLoadGeneratorServersInfo...
Àñèíõðîííîå ïðîãðàììèðîâàíèå
Êàê æå áûòü?
Àñèíõðîííîå ïðîãðàììèðîâàíèå
Êàê æå áûòü? Âñïîìèíàåì óðîêè ôóíêöèîíàëüíîãî
ïðîãðàììèðîâàíèÿ.
Èçáàâèòüñÿ îò ñèíòàêñè÷åñêîãî...
Àñèíõðîííîå ïðîãðàììèðîâàíèå
Êàê æå áûòü? Âñïîìèíàåì óðîêè ôóíêöèîíàëüíîãî
ïðîãðàììèðîâàíèÿ.
Èçáàâèòüñÿ îò ñèíòàêñè÷åñêîãî...
Àñèíõðîííîå ïðîãðàììèðîâàíèå
Êàê æå áûòü? Âñïîìèíàåì óðîêè ôóíêöèîíàëüíîãî
ïðîãðàììèðîâàíèÿ.
Èçáàâèòüñÿ îò ñèíòàêñè÷åñêîãî...
Àñèíõðîííîå ïðîãðàììèðîâàíèå
Îñíîâíàÿ èäåÿ:
interface AsyncT {
void run(CallbackT onOk, CallbackThrowable onError);
}
Ýòè ...
Àñèíõðîííîå ïðîãðàììèðîâàíèå
Ó÷èìñÿ ó .NET âîîáùå è F# â ÷àñòíîñòè.
let AsyncHttp(url:string) =
async { // Create the web ...
Àñèíõðîííîå ïðîãðàììèðîâàíèå
class AsyncPrimitives {
AsyncT succeed(T value) {...}
AsyncT failwith(Throwable error) {...}
...
Àñèíõðîííîå ïðîãðàììèðîâàíèå
Ìîíàäû ïðîíèêëè â ìåéíñòðèì: ó C# òåïåðü òîæå ó÷èìñÿ
(LINQ).
var requests = new[]
{
WebReques...
Àñèíõðîííîå ïðîãðàììèðîâàíèå
Ìîíàäû ïðîíèêëè â ìåéíñòðèì: ó C# òåïåðü òîæå ó÷èìñÿ
(LINQ).
var pages = from request in requ...
Àñèíõðîííîå ïðîãðàììèðîâàíèå
Ìîíàäû ïðîíèêëè â ìåéíñòðèì: ó C# òåïåðü òîæå ó÷èìñÿ
(LINQ).
foreach (var page in pages)
{
pa...
Àñèíõðîííîå ïðîãðàììèðîâàíèå
Further reading:
Î÷åíü èíòåðåñíûé ïîäõîä ñ èñïîëüçîâàíèåì yield return:
http://tomasp.net/blo...
Further reading
Ðàçíûå ïàòòåðíû ìíîãîïîòî÷íîãî è ðàñïðåäåëåííîãî
ïðîãðàììèðîâàíèÿ. Î÷åíü ìíîãî è èíòåðåñíî.
http://www.cs....
Ñîäåðæàíèå
Êîððåêòíîñòü
Ïðè÷èíû áàãîâ
Äîêàçàòåëüñòâî êîððåêòíîñòè
Óëó÷øåíèå êîððåêòíîñòè
Ïàòòåðíû è ïîäõîäû
Ïàðàëëåëèçì
Co...
Cutting edge
×òî óìååò Haskell:
Âñå ïîáî÷íûå ýôôåêòû êîíòðîëèðóþòñÿ
Íåò íåêîíòðîëèðóåìûõ ïðîáëåì èç-çà èõ íàëè÷èÿ
Ïîçâîëÿå...
Cutting edge
×òî óìååò Haskell:
Ñàìûå áûñòðûå â ìèðå ëåãêîâåñíûå íèòè è ïðèìèòèâû
ñèíõðîíèçàöèè
I ìåñòî íà v—ngu—ge ƒhooto...
Ëåãêîâåñíûå íèòè
Nothing special, ïðîñòî î÷åíü áûñòðûå è ïî÷òè 0
ñèíòàêñè÷åñêîãî îâåðõåäà.
C++0x futures/promises and more...
Ïàðàëëåëüíûå ñòðàòåãèè
Ëåíèâîñòü ïîçâîëÿåò îòäåëèòü àëãîðèòì è ñïîñîá
ðàñïàðàëëåëèâàíèÿ.
Ðåçóëüòàò àëãîðèòìà  ñòðóêòóðà, ï...
Ïàðàëëåëüíûå ñòðàòåãèè
Íàïðèìåð, ñòðàòåãèÿ
”
ïàðàëëåëüíî ôîðñèðîâàòü âñå ýëåìåíòû
ñïèñêà“:
parList :: Strategy a - Strateg...
Data Parallel Haskell
Âåêòîðèçàòîð (òðàíñëèðóåò äàæå ðåêóðñèâíûå ôóíêöèè â
âåêòîðíûå îïåðàöèè)
Áèáëèîòåêà ïàðàëëåëüíûõ âåê...
Data Parallel Haskell
sort :: [:Float:] - [:Float:]
sort a = if (length a = 1) then a
else sa!0 +++ eq +++ sa!1
where
m = ...
Repa
Regular, shape-polymorphic, parallel arrays in Haskell.
The Haskell code transparently makes use of multicore hardwar...
Òðàíçàêöèîííàÿ ïàìÿòü
transfer :: Account - Account - Int - IO ()
transfer from to amount = atomically do
deposit to amoun...
Òðàíçàêöèîííàÿ ïàìÿòü
check True = return ()
check False = retry
limitedWithdraw :: Account - Int - STM ()
limitedWithdraw...
Erlang
Ñâÿçü ïðîöåññîâ òîëüêî ÷åðåç îáìåí ñîîáùåíèÿìè.
Selective receive (èçáèðàòåëüíàÿ âûáîðêà èç mailbox).
Ìîùíàÿ ôè÷àF
...
F#
Asynchronous workows: óæå ðàññìîòðåëè.
C#
Asynchronous LINQ (ìîæíî ñäåëàòü ñàìîìó: LINQ =
ìîíàäû)
Óæå ðàññìîòðåëè
Parallel LINQ
Parallel LINQ (PLINQ)
IEnumerableT, IParallelEnumerableT
AsParallel
http://msdn.microsoft.com/en-us/magazine/cc163329.aspx
Parallel LINQ (PLINQ)
IEnumerableT data = ...;
var q = from x in data.AsParallel()
where p(x)
orderby k(x)
select f(x);
fo...
Parallel LINQ (PLINQ)
IEnumerableT leftData = ..., rightData = ...;
var q = from x in leftData.AsParallel()
join y in righ...
Clojure
Clojure is to concurrent programming as Java was to OOP
Áèáëèîòåêà ÷èñòî ôóíêöèîíàëüíûõ ñòðóêòóð äàííûõ
4 ìåõàíèçì...
Atoms
Áîëåå èëè ìåíåå îáû÷íûå atomic ïåðåìåííûå.
(swap! atom f)
”
Àòîìàðíî çàìåíèòü x íà f (x), âåðíóòü
ñòàðûé x (compare-...
Vars
Thread-local, dynamically scoped ïåðåìåííûå.
(def x 0) îáúÿâèòü x ñ ãëîáàëüíûì çíà÷åíèåì ïî
óìîë÷àíèþ 0.
x ïðî÷èòàòü ...
Agents
Àñèíõðîííî èçìåíÿåìûå ïåðåìåííûå.
(agent 0) àãåíò ñ íà÷àëüíûì çíà÷åíèåì 0
(deref x) òåêóùåå çíà÷åíèå
(send x f) àñè...
Refs
Òðàíçàêöèîííàÿ ïàìÿòü (STM).
Äîâîëüíî îáû÷íàÿ
Òðàíçàêöèè äîëæíû áûòü áåç ïîáî÷íûõ ýôôåêòîâ
Ëþáîïûòíî: (commute x f): ...
Ñîäåðæàíèå
Êîððåêòíîñòü
Ïðè÷èíû áàãîâ
Äîêàçàòåëüñòâî êîððåêòíîñòè
Óëó÷øåíèå êîððåêòíîñòè
Ïàòòåðíû è ïîäõîäû
Ïàðàëëåëèçì
Co...
×òî áûëî
Êëàññèôèêàöèÿ ìíîãîïîòî÷íûõ ïðîãðàìì
Ôîðìàëüíûå ìåòîäû (LTL) è òóëû (SPIN,JPF,CheckThread)
Êîððåêòíîñòü: èíêàïñóë...
The end
Ñïàñèáî! Âîïðîñû?
Ñîäåðæàíèå
Êîððåêòíîñòü
Ïðè÷èíû áàãîâ
Äîêàçàòåëüñòâî êîððåêòíîñòè
Óëó÷øåíèå êîððåêòíîñòè
Ïàòòåðíû è ïîäõîäû
Ïàðàëëåëèçì
Co...
Java Memory Model
Ãðóáî: Íàáîð àêñèîì î òîì, êàêèå ïðîèñøåñòâèÿ â ïàìÿòè êîìó
è êîãäà âèäèìû.
×òîáû êîìïèëÿòîð ìîã âûïîëíÿ...
Ïðèìåð
private int x, y;
void foo() {
x = 5;
y = 7;
}
void bar() {
if(x==5) {
// Íåâåðíî, ÷òî y==7
}
}
nal ïîëÿ è JMM
Ïðèìåð
public final class Foo {
private int x;
Foo(int x) {this.x = x;}
int getX() {return x; }
}
Íå thread...
Java Memory Model
Áîëåå òî÷íî: Íàáîð àêñèîì î òîì, êàêèå íàáëþäåíèÿ
ðåçóëüòàòîâ ïîñëåäîâàòåëüíîñòè äåéñòâèé â ïàìÿòè 
âîçì...
Java Memory Model
Âëèÿþùèå ôàêòîðû:
synchronized
volatile
final
Java Memory Model
Îñíîâíûå ïîíÿòèÿ:
Äåéñòâèå
Îáðàùåíèå ê ðàçäåëÿåìûì ïåðåìåííûì
ÂõîäGâûõîä èç ìîíèòîðà
ÇàïóñêGîæèäàíèå íèò...
×òî âñå-òàêè äåëàåò volatile?
×òåíèå îäíîé volatile ïåðåìåííîé  ïî÷òè òî÷êà
ñèíõðîíèçàöèè.
class VolatileExample {
int x =...
×òî âñå-òàêè äåëàåò nal?
Ïîñëå êîíñòðóèðîâàíèÿ final ïîëÿ âèäèìû.
Âèäèìû òàêæå îáúåêòû, äîñòóïíûå ÷åðåç íèõ
Ññûëêà íà îáúå...
Ïðîèçâîäèòåëüíîñòü
×òî òîðìîçèò?
Æäóùèå íèòè
Çàõâàò (äàæå óñïåøíûé) áëîêèðîâîê
Ïåðåêëþ÷åíèå êîíòåêñòîâ
Ïðîèçâîäèòåëüíîñòü
×òî äåëàòü?
Íå æäàòü è íå áëîêèðîâàòüñÿ
Íå ïåðåêëþ÷àòüñÿ
Óìåíüøåíèå áëîêèðîâîê
Êàê íå æäàòü?
Èñïîëüçîâàòü íåáëîêèðóþùèå àëãîðèòìû è îïåðàöèè
Óâåëè÷èòü ãðàíóëÿðíîñòü áëîêèðîâîê
Àíò...
Íåáëîêèðóþùèå àëãîðèòìû è îïåðàöèè
Áàçèñ:
get, set, getAndSet
boolean compareAndSet(expect, update) (CAS)
Ïîìåíÿòü ñ expec...
Íåáëîêèðóþùèå àëãîðèòìû è îïåðàöèè
Ñðåäñòâà â Java:
java.util.concurrent.atomic
AtomicInteger, AtomicLong
AtomicReference,...
Àòîìàðíûå îïåðàöèè
Ïðèìåð àëãîðèòìà íà CAS:
public class ConcurrentStackE {
AtomicReferenceNodeE head = new AtomicReferenc...
Íåáëîêèðóþùèå êîíòåéíåðû
Ãîòîâûå íåáëîêèðóþùèå ñòðóêòóðû äàííûõ (New in JDK6):
ConcurrentSkipListMap
ConcurrentSkipListSet...
Óìåíüøåíèå ãðàíóëÿðíîñòè áëîêèðîâîê
Áëîêèðóéòå íå âñ¼
Áëîêèðóéòå íå âñåõ
Óìåíüøåíèå ãðàíóëÿðíîñòè áëîêèðîâîê
Áëîêèðóéòå íå âñ¼:
Åñëè íàäî çàùèòèòü áîëüøóþ ñòðóêòóðó äàííûõ, íî ìåíÿþòñÿ
òîëüêî åå ...
Reader/Writer lock
Áëîêèðóéòå íå âñåõ:
×òåíèå ñîâìåñòèìî ñ ÷òåíèåì, íî íå ñ çàïèñüþ.
Áûâàþò ðàçíûå:
Readers-preference
Wri...
Ïåðåêëþ÷åíèå êîíòåêñòîâ
Êàê ïîìåíüøå ïåðåêëþ÷àòü êîíòåêñòû?
Èìåòü ïîìåíüøå íèòåé
ÍàïðèìåðD îäíó @iventEdrivenA
Ïîáîëüøå àñ...
Ïåðåêëþ÷åíèå êîíòåêñòîâ
Êàê ïîìåíüøå ïåðåêëþ÷àòü êîíòåêñòû?
Ïóñòü íèòè íå îòâëåêàþòñÿ.
Îäíè ïèõàþò çàäàíèÿ â î÷åðåäü
Äðóãè...
Öèôðû
Ñêîëüêî ðåàëüíî ñòîÿò ðàçëè÷íûå îïåðàöèè?
Àòîìàðíûå îïåðàöèè ≈ 0.1ìêñ; incAndGet
è volatile 2-3x áûñòðåå CAS
Ïåðåêëþ...
×òî óìååò JVM?
Biased locking
Lock coarsening
Lock elision (escape analysis)
http:
//www.infoq.com/articles/java-threading...
×òî óìååò JVM?
Biased locking (new in 1.5.0_6):
Áîëüøèíñòâî îáúåêòîâ çà âñþ æèçíü áëîêèðóåò òîëüêî 1
íèòü
Äåëàåòñÿ òàê, ÷ò...
×òî óìååò JVM?
Lock coarsening:
public void setupFoo(Foo foo) {
foo.setBarCount(1);
foo.setQuxEnabled(true);
foo.addGazonk...
×òî óìååò JVM?
Escape analysis: Åñëè îáúåêò íå óáåãàåò â äðóãóþ íèòü, òî íåò
ñìûñëà äåëàòü íà íåì synchronized.
DeepThough...
Òåñòèðîâàíèå
Òåñòèðîâàòü ìíîãîïîòî÷íûé êîä àäñêè ñëîæíî.
Ïðîòåñòèðîâàòü ïðàâèëüíîñòü äåòåðìèíèðîâàííîãî êîäà 
ìîæíî, õîòü ...
Òåñòèðîâàíèå
×òî íóæíî îòòåñòèðîâàòü?
Êîä ïîñëåäîâàòåëüíî êîððåêòåí
Êîä ïðàâèëüíî ðàáîòàåò áåç íàãðóçêè
Êîä íå ëîìàåòñÿ ïî...
Íàëè÷èå îæèäàåìîãî ïîâåäåíèÿ
Êàê ïðîâåðèòü, ÷òî ìíîãîïîòî÷íûé êîä ðåàëèçóåò
îïðåäåëåííûé ïðîòîêîë â èäåàëüíûõ óñëîâèÿõ?
Ïî...
Óñòîé÷èâîñòü ê íàãðóçêå
Êàê ïðîâåðèòü, ÷òî ìíîãîïîòî÷íûé êîä íå ëîìàåòñÿ ïîä
íàãðóçêîé?
Ïðèäóìàòü èíâàðèàíòû
Îðãàíèçîâàòü ...
Óñòîé÷èâîñòü ê íàãðóçêå
Ïðèìåð: Òåñòèðóåì ConcurrentMap.
Èíâàðèàíò: Êàæäûé äîáàâëåííûé, íî íå óäàëåííûé
ýëåìåíò ïðèñóòñòâó...
Óñòîé÷èâîñòü ê íàãðóçêå
Ïðèìåð: Òåñòèðóåì ConcurrentMap
Ïîâòîðèòü 100000000000000 ðàç
Ñãåíåðèðîâàòü IHHHH ñëó÷àéíûõ çíà÷åí...
Ïîâòîðÿåìîñòü
Êàê ïîâòîðèòü ãîòîâóþ îøèáêó?
Íàïèñàòü äåëåãèðóþùèå mock-îáúåêòû, çàïèñûâàþùèå âñå
äåéñòâèÿ
Äîæäàòüñÿ îøèáêè...
Êàê ñïðîâîöèðîâàòü îøèáêó
Êàê îðãàíèçîâàòü ìàêñèìóì íåäåòåðìèíèçìà øåäóëåðà?
Ïîíàñòàâèòü Thread.yield() èëè Thread.sleep(1...
×òî äåëàòü ñ ïðîèçîøåäøèìè îøèáêàìè
Ãëàâíîå  íå äàòü èì óñêîëüçíóòü.
Íå äàâàòü
”
îãíåîïàñíûå“ âû÷èñëåíèÿ âíåøíèì API  îíè
...
×òî äåëàòü ñ ïðîèçîøåäøèìè îøèáêàìè
Ãëàâíîå  íå äàòü èì óñêîëüçíóòü.
Íå äàâàòü
”
îãíåîïàñíûå“ âû÷èñëåíèÿ âíåøíèì API  îíè
...
Òóëû
TestNG èìååò íåáîëüøèå ñïåöèàëüíûå ñðåäñòâà
@Test(threadPoolSize=5,invocationCount=10,threadMap=2,2,2,3,1)
Multithrea...
Евгений Кирпичёв   Многопоточное программирование (Full)
Евгений Кирпичёв   Многопоточное программирование (Full)
Евгений Кирпичёв   Многопоточное программирование (Full)
Upcoming SlideShare
Loading in...5
×

Евгений Кирпичёв Многопоточное программирование (Full)

628

Published on

Published in: Technology, News & Politics
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
628
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
5
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Transcript of "Евгений Кирпичёв Многопоточное программирование (Full)"

  1. 1. Ìíîãîïîòî÷íîå ïðîãðàììèðîâàíèå è Java Êîððåêòíîñòü, ïàòòåðíû, ïîäõîäû Åâãåíèé Êèðïè÷¼â 18 àïðåëÿ 2010 ã. Îáñóæäåíèå: http://community.livejournal.com/ru_java/929773.html
  2. 2. Öåëü äîêëàäà Ðàñøèðèòü êðóãîçîð â îáëàñòè ìíîãîïîòî÷íîãî ïðîãðàììèðîâàíèÿ âîîáùå è íà Java â ÷àñòíîñòè. Êîððåêòíîñòü Êàê ñôîðìóëèðîâàòüD ïîâûñèòüD ãàðàíòèðîâàòü Èíñòðóìåíòû Ïàòòåðíû è âåëîñèïåäû Ïîäõîäû è ôèøêè ðàçíûõ ÿçûêîâ
  3. 3. Êëàññèôèêàöèÿ ìíîãîïîòî÷íûõ ïðîãðàìì Parallelism vs Concurrency Parallel Îäíà çàäà÷à áüåòñÿ íà ìíîãî ÷àñòåé Concurrent Ìíîãî ðàçíûõ çàäà÷ (ñëîæíåå) Ñåãîäíÿ â îñíîâíîì î concurrency.
  4. 4. Ïðîáëåìû ìíîãîïîòî÷íîãî ïðîãðàììèðîâàíèÿ Ïèñàòü concurrent ïðîãðàììû òðóäíî. Îáû÷íî ñëàáàÿ ïîääåðæêà ñî ñòîðîíû ÿçûêà Òðóäíî íå îøèáèòüñÿ Î÷åíü òðóäíî òåñòèðîâàòü
  5. 5. Êëàññèôèêàöèÿ ìíîãîïîòî÷íûõ ïðîãðàìì (contd.) Ïðîãðàììû áûâàþò ðàçíûå. Raytracer Server IDE Ñêîëüêî çàäà÷? Ìíîãî Ìíîãî Ìàëî Çàâèñèìû? Íåò Íåò Äà Îáùèå ðåñóðñû? Íåò Äà Äà Òðóäíîñòü CPU perf IO perf Êîððåêòíîñòü
  6. 6. ×àñòü 1. Êîððåêòíîñòü.
  7. 7. Ñîäåðæàíèå Êîððåêòíîñòü Ïðè÷èíû áàãîâ Äîêàçàòåëüñòâî êîððåêòíîñòè Óëó÷øåíèå êîððåêòíîñòè Ïàòòåðíû è ïîäõîäû Ïàðàëëåëèçì Concurrency Cutting edge Haskell Erlang .NET Clojure Çàêëþ÷åíèå Appendix Java memory model Ïðîèçâîäèòåëüíîñòü Òåñòèðîâàíèå è íàáëþäàåìîñòü
  8. 8. Ïðè÷èíû áàãîâ Êîðåíü âñåõ çîë èçìåíÿåìîå âî âðåìåíè ñîñòîÿíèå. N íèòåé, K ñîñòîÿíèé ⇒ O(KN) ïåðåïëåòåíèé Ïðîìåæóòî÷íûå ñîñòîÿíèÿ âèäèìû Äàæå âûçîâ ìåòîäà ýòî áîëüøå íå ÷åðíûé ÿùèê Åãî òåëî áîëüøå íå àòîìàðíî Êîððåêòíûå ìíîãîïîòî÷íûå ïðîãðàììû íå ìîäóëüíû ƒequenti—ly ™orre™t + ƒequenti—lly ™orre™t = gon™urrently ™orre™t
  9. 9. Ïðè÷èíû áàãîâ Sequentialy correct + Sequentially correct = Concurrently correct
  10. 10. Äîêàçóåìàÿ êîððåêòíîñòü Face it: Ëèáî ïðîãðàììà äîêàçóåìî êîððåêòíà Ëèáî îíà, ïî÷òè íàâåðíÿêà, íåêîððåêòíà Ïóñòü âåðîÿòíîñòü áàãà 10−8 109 âûçîâîâ çà íåäåëþ è âåðîÿòíîñòü 1 − e−10 ≈ 1 Ïðè íåïðåðûâíîì òåñòèðîâàíèè îøèáêà òîæå âñïëûâåò òîëüêî ÷åðåç íåäåëþ Ðàáîòàåò íà áóìàãå èëè íå ðàáîòàåò âîîáùå
  11. 11. Äîêàçóåìàÿ êîððåêòíîñòü Face it: Ëèáî ïðîãðàììà äîêàçóåìî êîððåêòíà Ëèáî îíà, ïî÷òè íàâåðíÿêà, íåêîððåêòíà Tony Hoare: There are two ways of constructing a software design. One way is to make it so simple that there are obviously no deciencies, and the other way is to make it so complicated that there are no obvious deciencies. The rst method is far more dicult.
  12. 12. Ôîðìàëüíûå ìåòîäû Ïðèìåíÿòü íå îáÿçàòåëüíî.
  13. 13. Ôîðìàëüíûå ìåòîäû À çà÷åì òîãäà îíè âîîáùå íóæíû? ×òîáû îïèñûâàòü ñèñòåìó ïîëóôîðìàëüíî ×òîáû ÷óÿòü: ôîðìàëèçóåìà ëè ñèñòåìà â ïðèíöèïå? Åñëè íåò @ñèñòåìà ñëèøêîì çàïóòàíàA î êîððåêòíîñòè ìîæíî çàáûòüF
  14. 14. Ôîðìàëüíûå ìåòîäû Ìîé îïûò: äîñòàòî÷íî ïîïûòàòüñÿ ôîðìàëèçîâàòü ñèñòåìó: Âñïëûâàþò ïðîòèâîðå÷èÿ, íåäîãîâîðêè â òðåáîâàíèÿõ Âûäåëÿþòñÿ êîìïîíåíòû áåç ÷åòêîé ñïåöèôèêàöèè ÁëàæåíD êòî âåðóåòD ÷òî îíè ” è òàê“ ðàáîòàþò
  15. 15. Ôîðìàëüíûå ìåòîäû ×òî æå ýòî çà ìåòîäû? Íàïðèìåð, ëèíåéíàÿ òåìïîðàëüíàÿ ëîãèêà.
  16. 16. Äîêàçóåìàÿ êîððåêòíîñòü Ëèíåéíàÿ òåìïîðàëüíàÿ ëîãèêà ñïîñîá ðàññóæäàòü î ïîñëåäîâàòåëüíîñòÿõ ñîáûòèé. Ïðîãðàììà ìîäåëèðóåòñÿ àâòîìàòîì ( ” ñòðóêòóðîé Êðèïêå“). Èññëåäóþòñÿ âîçìîæíûå ïîñëåäîâàòåëüíîñòè ñîñòîÿíèé.
  17. 17. Ñòðóêòóðà Êðèïêå Ñòðóêòóðà Êðèïêå ≈ ãðàô ñîñòîÿíèé. Ìíîæåñòâî ñîñòîÿíèé Íåêîòîðûå íà÷àëüíûå Íåêîòîðûå ñîåäèíåíû ïåðåõîäîì Ïåðåõîä áåçóñëîâíûé Ìíîæåñòâî ôàêòîâ  êàæäîì ñîñòîÿíèè âåðíû íåêîòîðûå ôàêòû.
  18. 18. Ñòðóêòóðà Êðèïêå Ìèêðîâîëíîâêà.
  19. 19. Ñòðóêòóðà Êðèïêå Ïåðåõîäû íå ïîäïèñàíû, ïîòîìó ÷òî: Íîìåð ñîñòîÿíèÿ ïîëíîñòüþ îïèñûâàåò ñîñòîÿíèå ïðîãðàììû Åñëè ïåðåõîä óñëîâíûé íàäî ïîäåëèòü ñîñòîÿíèå íà äâà ÒîD â êîòîðîì óñëîâèå âåðíî @ïåðåõîä ìîæåò ïðîèçîéòèA ÒîD â êîòîðîì óñëîâèå íåâåðíî @ïåðåõîä íå ìîæåò ïðîèçîéòèA Ïðîãðàììó ìîæíî ñòðàíñëèðîâàòü â ñòðóêòóðó Êðèïêå Ñòðóêòóðû Êðèïêå ïðåêðàñíî ïîääàþòñÿ âåðèôèêàöèè
  20. 20. LTL Ëèíåéíàÿ òåìïîðàëüíàÿ ëîãèêà (Linear Temporal Logic). Ðàññóæäàåò î ïîñëåäîâàòåëüíîñòÿõ ñîñòîÿíèé ìèðà âî âðåìåíè. Åñòü çàïðîñ ⇒ êîãäà-íèáóäü áóäåò îòâåò Áëîêèðîâêà çàïðîøåíà ⇒ êëèåíò áóäåò îáñëóæåí ñêîëü óãîäíî áîëüøîå ÷èñëî ðàç, ïîêà íå îòïóñòèò åå . . . Ïðåëåñòè: Êðàòêàÿ, ïîíÿòíàÿ, ìîùíàÿ è îäíîçíà÷íàÿ LTL-ñâîéñòâà ëåãêî âåðèôèöèðóþòñÿ äàæå âðó÷íóþ Îòíîñèòåëüíî ñòðóêòóð Êðèïêå Ìíîãî ìîùíûõ èíñòðóìåíòîâ
  21. 21. Ôîðìóëû LTL p1, p2, . . . Ïåðåìåííûå A ∧ B, ¬A. . . Ëîãè÷åñêèå ñâÿçêè XA  ñëåäóþùèé ìîìåíò A (neXt) GA ≡ A Âñåãäà A (Globally) FA ≡ ♦A Êîãäà-íèáóäü A (Future) AUB A, ïî êðàéíåé ìåðå äî íàñòóïëåíèÿ B
  22. 22. Áåñêîíå÷íîñòè Íà÷èíàÿ ñ íåêîòîðîãî ìîìåíòà, íàâñåãäà: FG A ≡ ♦ A Áåñêîíå÷íî ÷àñòî: GF A ≡ ♦A
  23. 23. Èëëþñòðàöèÿ ôîðìóë LTL
  24. 24. Ñâîéñòâà Æèâîñòü (liveness) ×òîEòî õîðîøåå êîãäàEíèáóäü ïðîèçîéäåòX ♦Alive Çàäàíèå êîãäàEíèáóäü íà÷íåòñÿ Áåçîïàñíîñòü (safety) ×òîEòî ïëîõîå íèêîãäà íå ïðîèçîéäåòX ¬Dead Çàäàíèå íèêîãäà íå ïîòåðïèò êðàõ
  25. 25. Ñâîéñòâà Ñïðàâåäëèâîñòü (fairness) Òî, ÷òî ìîæåò ïðîèçîéòè ïðîèçîéäåò Ñëàáàÿ: ♦ Req → ♦Ack Ðåñóðñ çàïðîøåí @è îñòàåòñÿ çàïðîøåííûìA → êîãäàEíèáóäü áóäåò âûäàí Ñèëüíàÿ: ♦Req → ♦Ack Íèòü áåñêîíå÷íî ìíîãî ðàç èñïîëíèìà @èìååò íå ñàìûé íèçêèé ïðèîðèòåò èç íåáëîêèðîâàííûõA → êîãäàEíèáóäü ïîëó÷èò êâàíò Àíòîíèì starvation (ãîëîäàíèå)
  26. 26. Ïðèìåðû LTL-ñâîéñòâ Óñòðîéñòâî íå âûêëþ÷àåòñÿ ñàìî ïî ñåáå (isOn → (isOn U (turnOPressed ∨ noBattery)) Íå ðåæå ÷åì ðàç â 5 òàêòîâ âêëþ÷àåòñÿ êîíòðîëëåð äâèãàòåëÿ F5(activeThread == ENGINE_CONTROLLER)
  27. 27. Model checking Íàóêà î ïðîâåðêå ñâîéñòâ ïðîãðàìì (íàïðèìåð, LTL) íà îñíîâå èõ ìîäåëåé (íàïðèìåð, ñòðóêòóð Êðèïêå) Model checking. Ïðåìèÿ Òüþðèíãà 2007 çà äîñòèæåíèÿ â îáëàñòè model checking, ñäåëàâøèå åãî ïðèìåíèìûì äëÿ ïðîåêòîâ ðåàëüíîãî ðàçìåðà.
  28. 28. Èíñòðóìåíò: SPIN Ïîâñåìåñòíî èñïîëüçóåìûé ÿçûê + âåðèôèêàòîð LTL-ñâîéñòâ äëÿ ìíîãîçàäà÷íûõ ñèñòåì. Ëàóðåàò ACM Software System award (2001) (äðóãèå ëàóðåàòû: Unix, TeX, Java, Apache, TCP/IP, . . . ). Ñè-ïîäîáíûé ñèíòàêñèñ Äëÿ íàðóøåííûõ ñâîéñòâ ãåíåðèðóåòñÿ íàðóøàþùàÿ èõ òðàññà (óðîäëèâûé, íî òåðïèìûé) GUI ß ïðîâåðÿë: Ïðèãîäíî äëÿ ïðèìåíåíèÿ íà ïðàêòèêå. http://spinroot.com/spin/whatispin.html îôèöèàëüíûé ñàéòF
  29. 29. AspectJ+LTL http://www.sable.mcgill.ca/~ebodde/rv/JLO/ tEvyX ïðîâåðÿåò v„vEñâîéñòâà â ðàíòàéìå @çàáðîøåíAF http://abc.comlab.ox.ac.uk/extensions „r—™e™he™kX ïðîäîëæåíèåD îò òåõ æå àâòîðîâX ïðîâåðÿåò ðåãóëÿðíûå âûðàæåíèÿ íàä òðàññàìè ïðîãðàììûF
  30. 30. Model checking:further reading http://www.inf.unibz.it/~artale/FM/slide3.pdf Òóòîðèàë ïî v„vF http: //citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.60.3062 Ñòàòüÿ ïðî tEvy http://spinroot.com/spin/Doc/course/mc-tutorial.pdf wodel ghe™kingX e tutori—l overview @ìíîãî ññûëîêA Êàðïîâ ÞF ÃF wodel ™he™king @ïðîäàåòñÿ â ìàãàçèíàõAF http://savenkov.lvk.cs.msu.su/mc.html Èíòåðåñíûé êóðñ â ÌÃÓ @‡s€AF
  31. 31. Áëèæå ê äåëó Êàê ðàññóæäàòü î ðåàëüíûõ ïðîãðàììàõ? Àêñèîìàòèêà: Java memory model è ò.ï. Îñíîâíûå ïàðàìåòðû (äîêóìåíòèðóéòå èõ!): „hre—d s—fety Âîçìîæíîñòü áëîêèðîâàíèÿY èñïîëüçóåìûå áëîêèðîâêè è ïîðÿäîê èõ âçÿòèÿ Âåðõíÿÿ ãðàíèöà âðåìåíè âûïîëíåíèÿ @êîíñòàíòà èëè íåòA Ðåàêöèÿ íà ïðåðûâàíèå Ðåàêöèÿ íà îøèáêè Ðåàêöèÿ íà òàéìàóòû F F F
  32. 32. Java Memory Model Ñ íåé íåîáõîäèìî îçíàêîìèòüñÿ. Ìíîãî ñþðïðèçîâ. Íåëüçÿ ñîçäàâàòü íèòè â êîíñòðóêòîðå Íå-nal ïîëÿ íå ïîòîêîáåçîïàñíû (äàæå åñëè íå ìåíÿþòñÿ) . . . Ñì. appendix, êíèãó JCIP, JLS.
  33. 33. Thread safety Immutable. Ó îáúåêòà âñåãî 1 ñîñòîÿíèå. Thread-safe. Êàæäàÿ îïåðàöèÿ ñàìà ïî ñåáå áåçîïàñíà/àòîìàðíà. Ïîñëåäîâàòåëüíîñòè íåò. Ïîñëåäîâàòåëüíîñòè íóæíî êîîðäèíèðîâàòü èçâíå ÄîêóìåíòèðóéòåD êàêèå èìåííî âñåEòàêè áåçîïàñíû ÏðèìåðX Áàíêîâñêèé ñ÷åò
  34. 34. Thread safety Thread-compatible. Ìîæíî èñïîëüçîâàòü ìíîãîïîòî÷íî, åñëè íå âûçûâàòü îïåðàöèè îäíîâðåìåííî. Íóæíà âíåøíÿÿ ñèíõðîíèçàöèÿD íî ñ íåé áóäåò ðàáîòàòü Thread-hostile. Âîîáùå íåëüçÿ èñïîëüçîâàòü ìíîãîïîòî÷íî. Thread-conned. Ìîæíî èñïîëüçîâàòü èç êîíêðåòíîé íèòè. ÏðèìåðX ƒwing
  35. 35. CheckThread Íàáîð àííîòàöèé äëÿ äîêóìåíòèðîâàíèÿ thread safety. Åñòü ïëàãèí ê IDEA. Î÷åíü ïîëåçíî. Ïðèìåð @ThreadSafe class SynchronizedInteger { @GuardedBy(this) private int value; synchronized int get() { return value; } synchronized void set(int v) { value = v; } }
  36. 36. Java Path Finder Âèðòóàëüíàÿ ìàøèíà, óìåþùàÿ ñèìâîëüíî âûïîëíÿòü Java-êîä è âåðèôèöèðîâàòü ñâîéñòâà äëÿ âñåõ âîçìîæíûõ çàïóñêîâ ñ ó÷åòîì ìíîãîïîòî÷íîñòè. Ñäåëàíî â NASA. http://javapathfinder.sourceforge.net/ http://sourceforge.net/projects/visualjpf/ q…s http://www.visserhome.com/willem/presentations/ ase06jpftut.ppt ïîäîáèå òóòîðèàëà ÓòâåðæäàåòñÿD ÷òî ñïðàâëÿåòñÿ ñ ïðîåêòàìè äî IHuvygF Íàõîäèë áàãè â xeƒeEîâñêîì ñîôòå @â ìàðñîõîäåD íàïðèìåðA Îñíîâàí íà ƒ€sx Åñòü —ntEt—sk è ïëàãèí ê e™lipseY ðàñøèðÿåì ß íàïèñàë ìàëåíüêèé ïðèìåð ñ äåäëîêîìF ÑðàáîòàëîF
  37. 37. Äðóãèå òóëû Ñòàòè÷åñêèé àíàëèç ìíîãîïîòî÷íûõ îøèáîê åñòü è â: PMD FindBugs (åñòü ïëàãèí ê IDEA) Ïðîâåðåíî: ïîìîãàåò (è íå òîëüêî îò ìíîãîïîòî÷íûõ).
  38. 38. Ôèëîñîôñêîå èçáàâëåíèå îò áàãîâ Íàäî óìåíüøèòü O(KN). Óìåíüøèòü ÷èñëî íàáëþäàåìûõ ñîñòîÿíèé (K) smmut—˜ility Èíêàïñóëÿöèÿ ñîñòîÿíèÿ Âûñîêîóðîâíåâûå îïåðàöèè Ôàêòîðèçàöèÿ Ñèíõðîíèçàöèÿ Íàâÿçàòü òðàññàì ýêâèâàëåíòíîñòü Èäåìïîòåíòíûå îïåðàöèè foo();foo(); ∼ foo(); Êîììóòàòèâíûå @íåçàâèñèìûåA îïåðàöèè foo();bar(); ∼ bar();foo();  ò.÷. èíêàïñóëÿöèÿ è íåçàâèñèìûå îáúåêòû Ñ÷èòàòü áîëüøåå ÷èñëî òðàññ êîððåêòíûìè (îñëàáèòü òðåáîâàíèÿ)
  39. 39. Immutability Íåëüçÿ èçìåíèòü âîîáùå ⇒ íåëüçÿ èçìåíèòü íåïðàâèëüíî, íå â òîì ïîðÿäêå . . . Âñå ïîëÿ private, nal, è èõ êëàññû ñàìè ïî ñåáå immutable Èíà÷å ïîëå ìîæåò èçìåíèòü êòîEòî äðóãîé Èíà÷å íàðóøèòñÿ thre—d s—fety @t—v— wemory wodelA Èíà÷å èçìåíåíèå ìîæåò ïðîèçîéòè òàéêîì Ñàì êëàññ nal Èíà÷å ìîæíî ñîçäàòü mut—˜le ïîòîìêà è ïåðåäàòü åãî êîìóEíèáóäü â êà÷åñòâå îáúåêòà áàçîâîãî êëàññà Áàçîâûé êëàññ òîæå immutable Èíà÷å ìîæíî èçìåíèòü ñîñòîÿíèå ïðè ïîìîùè îïåðàöèé áàçîâîãî êëàññà
  40. 40. Immutability Íåëüçÿ èçìåíèòü âîîáùå ⇒ íåëüçÿ èçìåíèòü íåïðàâèëüíî, íå â òîì ïîðÿäêå . . . Âñå ïîëÿ private, nal, è èõ êëàññû ñàìè ïî ñåáå immutable Èíà÷å ïîëå ìîæåò èçìåíèòü êòîEòî äðóãîé Èíà÷å íàðóøèòñÿ thre—d s—fety @t—v— wemory wodelA Èíà÷å èçìåíåíèå ìîæåò ïðîèçîéòè òàéêîì Ñàì êëàññ nal Èíà÷å ìîæíî ñîçäàòü mut—˜le ïîòîìêà è ïåðåäàòü åãî êîìóEíèáóäü â êà÷åñòâå îáúåêòà áàçîâîãî êëàññà Áàçîâûé êëàññ òîæå immutable Èíà÷å ìîæíî èçìåíèòü ñîñòîÿíèå ïðè ïîìîùè îïåðàöèé áàçîâîãî êëàññà
  41. 41. Immutability Íåëüçÿ èçìåíèòü âîîáùå ⇒ íåëüçÿ èçìåíèòü íåïðàâèëüíî, íå â òîì ïîðÿäêå . . . Âñå ïîëÿ private, nal, è èõ êëàññû ñàìè ïî ñåáå immutable Èíà÷å ïîëå ìîæåò èçìåíèòü êòîEòî äðóãîé Èíà÷å íàðóøèòñÿ thre—d s—fety @t—v— wemory wodelA Èíà÷å èçìåíåíèå ìîæåò ïðîèçîéòè òàéêîì Ñàì êëàññ nal Èíà÷å ìîæíî ñîçäàòü mut—˜le ïîòîìêà è ïåðåäàòü åãî êîìóEíèáóäü â êà÷åñòâå îáúåêòà áàçîâîãî êëàññà Áàçîâûé êëàññ òîæå immutable Èíà÷å ìîæíî èçìåíèòü ñîñòîÿíèå ïðè ïîìîùè îïåðàöèé áàçîâîãî êëàññà
  42. 42. Immutability Íåëüçÿ èçìåíèòü âîîáùå ⇒ íåëüçÿ èçìåíèòü íåïðàâèëüíî, íå â òîì ïîðÿäêå . . . Âñå ïîëÿ private, nal, è èõ êëàññû ñàìè ïî ñåáå immutable Èíà÷å ïîëå ìîæåò èçìåíèòü êòîEòî äðóãîé Èíà÷å íàðóøèòñÿ thre—d s—fety @t—v— wemory wodelA Èíà÷å èçìåíåíèå ìîæåò ïðîèçîéòè òàéêîì Ñàì êëàññ nal Èíà÷å ìîæíî ñîçäàòü mut—˜le ïîòîìêà è ïåðåäàòü åãî êîìóEíèáóäü â êà÷åñòâå îáúåêòà áàçîâîãî êëàññà Áàçîâûé êëàññ òîæå immutable Èíà÷å ìîæíî èçìåíèòü ñîñòîÿíèå ïðè ïîìîùè îïåðàöèé áàçîâîãî êëàññà
  43. 43. Immutability Íåëüçÿ èçìåíèòü âîîáùå ⇒ íåëüçÿ èçìåíèòü íåïðàâèëüíî, íå â òîì ïîðÿäêå . . . Âñå ïîëÿ private, nal, è èõ êëàññû ñàìè ïî ñåáå immutable Èíà÷å ïîëå ìîæåò èçìåíèòü êòîEòî äðóãîé Èíà÷å íàðóøèòñÿ thre—d s—fety @t—v— wemory wodelA Èíà÷å èçìåíåíèå ìîæåò ïðîèçîéòè òàéêîì Ñàì êëàññ nal Èíà÷å ìîæíî ñîçäàòü mut—˜le ïîòîìêà è ïåðåäàòü åãî êîìóEíèáóäü â êà÷åñòâå îáúåêòà áàçîâîãî êëàññà Áàçîâûé êëàññ òîæå immutable Èíà÷å ìîæíî èçìåíèòü ñîñòîÿíèå ïðè ïîìîùè îïåðàöèé áàçîâîãî êëàññà
  44. 44. Èíêàïñóëÿöèÿ ñîñòîÿíèÿ Ïðîãðàììà êîððåêòíà ðîâíî íàñòîëüêî, íàñêîëüêî êîððåêòíû è ñêîîðäèíèðîâàíû âñå, êòî ìîãóò ïîâëèÿòü íà ñîñòîÿíèå îáúåêòà. Ìîðàëü: ×åì ìåíüøå ñïîñîáîâ ïîâëèÿòü íà ñîñòîÿíèå, òåì ëó÷øå. Ìàëî êîìó äàâàòü ê íåìó äîñòóï Ìàëî êîãî íàäî áóäåò êîîðäèíèðîâàòü Äàâàòü äîñòóï â òåðìèíàõ ìàëîãî ÷èñëà âûñîêîóðîâíåâûõ îïåðàöèé Ìàëî êîìáèíàöèé îïåðàöèé íàäî ðàññìàòðèâàòü Ìåíüøå íàðóøàåòñÿ öåëîñòíîñòü ìåæäó îïåðàöèÿìè
  45. 45. Âûñîêîóðîâíåâûå îïåðàöèè Îïðåäåëåíèå: Âûñîêîóðîâíåâàÿ îïåðàöèÿ îïåðàöèÿ, íå íàðóøàþùàÿ öåëîñòíîñòü ñèñòåìû. AtomicInteger.getAndIncrement ConcurrentMap.putIfAbsent Bank.transfer Äîñòàòî÷íî ïðàâèëüíî ðåàëèçîâàòü ñàìó îïåðàöèþ. Ïðîåêòèðóéòå API â òàêîì ñòèëå, åñëè ýòî âîçìîæíî.
  46. 46. Âûñîêîóðîâíåâûå îïåðàöèè ×àñòíûé ñëó÷àé: Ó îáúåêòà â ìåðó áîëüøîå ñîñòîÿíèå Õî÷åòñÿ àòîìàðíî ïîìåíÿòü íåñêîëüêî åãî ÷àñòåé Çàïèõíèòå ñîñòîÿíèå â îáúåêò è ïîìåíÿéòå àòîìàðíî ññûëêó íà ýòîò îáúåêò AtomicReference ×èñòî ôóíêöèîíàëüíûå ñòðóêòóðû äàííûõ âñåãäà ïîòîêîáåçîïàñíû http://tobega.blogspot.com/2008/03/ java-thread-safe-state-design-pattern.html ÑìFòæF yk—s—kiD €urely fun™tion—l d—t— stru™turesF
  47. 47. Ôàêòîðèçàöèÿ Ïðîãðàììà êîððåêòíà ðîâíî íàñòîëüêî, íàñêîëüêî êîððåêòíû è ñêîîðäèíèðîâàíû âñå, êòî ìîãóò ïîâëèÿòü íà ñîñòîÿíèå îáúåêòà. Ìîðàëü: Íåçàâèñèìûå àñïåêòû ñîñòîÿíèÿ âûíîñèòü â íåçàâèñèìûå îáúåêòû. Ñëîæíîñòü ïàäàåò ñ (K1 + K2)N äî KN 1 + KN 2 (áðåä, íî ñóòü ïðèìåðíî òàêàÿ).
  48. 48. Ôàêòîðèçàöèÿ class DataLoader { ClientToken beginLoad(Client client); void writeData(ClientToken token, Data data); void commit(ClientToken token); void rollback(ClientToken token); }
  49. 49. Ôàêòîðèçàöèÿ Ñëîæíûé êîä: Òàáëèöà ClientToken/òðàíçàêöèÿ (ìíîãîïîòî÷íûå êëèåíòû) synchronized(locks.get(token))
  50. 50. Ôàêòîðèçàöèÿ Ðàçîðâåì ëèøíþþ çàâèñèìîñòü ìåæäó íåçàâèñèìûìè çàäà÷àìè. class DataLoader { PerClientLoader beginLoad(Client client); } class PerClientLoader { void writeData(Data data); void commit(); void rollback(); }
  51. 51. Ôàêòîðèçàöèÿ Ïðîñòîé è íåçàãðÿçíåííûé êîä Ñèíõðîíèçàöèÿ ïðîñòûì synchronized Íèêàêèõ òàáëèö Íèêàêèõ ïðîáëåì ñ îõðàíîé òàáëèö îò ìíîãîïîòî÷íîãî äîñòóïà
  52. 52. Ñèíõðîíèçàöèÿ (ñåðèàëèçàöèÿ äîñòóïà) Ýòî âñå çíàþò: Õî÷åøü çàùèòèòü îáúåêò ñäåëàé íà íåì synchronized.
  53. 53. Ñèíõðîíèçàöèÿ (ñåðèàëèçàöèÿ äîñòóïà) Åñëè íàäî çàùèòèòü äîñòóï ê êîìáèíàöèè îáúåêòîâ íàäî ñèíõðîíèçèðîâàòüñÿ â îäèíàêîâîì ïîðÿäêå. Èíà÷å äåäëîêè. Òàê äåëàòü íå íàäî void foo() { synchronized(x) { synchronized(y) { ... } } } void bar() { synchronized(y) { synchronized(x) { ... } } }
  54. 54. Áîðüáà ñ äåäëîêàìè Íóæåí ãëîáàëüíî ôèêñèðîâàííûé ïîðÿäîê áëîêèðîâîê. Ýêçîòè÷åñêèé ñëó÷àé: Òàê äåëàòü íå íàäî void transfer(Account from,Account to,int money) { synchronized(from) { synchronized(to) { .. } } }
  55. 55. Áîðüáà ñ äåäëîêàìè: Ýêçîòè÷åñêèé ñëó÷àé Íóæåí ãëîáàëüíî ôèêñèðîâàííûé ïîðÿäîê áëîêèðîâîê. Íàäî äåëàòü âîò òàê void transfer(Account from,Account to,int money) { synchronized(fromto ? from : to) { synchronized(from?to ? to : from) { .. } } } Ïîäðîáíî ñì. Java Concurrency in Practice.
  56. 56. Åùå íåìíîãî î äåäëîêàõ Íå ñòîèò âûçûâàòü ÷óæèå ìåòîäû (callbacks), äåðæà áëîêèðîâêó (alien call). Òàêèå âûçîâû ëó÷øå ïðåâðàòèòü â open call (âûçîâ âíå áëîêèðîâêè) private void frobbleBar(Bar bar) { ListBarListener copy; synchronized (this) { copy = new ArrayListBarListener(listeners); } for (Listener l : snapshot) l.barFrobbled(bar); } Áîëåå îáùèé ñëó÷àé: Ìèíèìèçèðóéòå ñëîæíîñòü è íåèçâåñòíîñòü êîäà âíóòðè áëîêèðîâêè Ñîâñåì õîðîøî, åñëè åãî äëèòåëüíîñòü îãðàíè÷åíà ñâåðõó
  57. 57. Åùå íåìíîãî î äåäëîêàõ ×àñòàÿ ïðè÷èíà äåäëîêîâ ðåñóðñû è ïóëû. Äîñòóï ê ðåñóðñàì íàäî óïîðÿäî÷èâàòü, êàê è áëîêèðîâêè Ïóëû + âçàèìîçàâèñèìûå çàäà÷è = ïðîáëåìà Thread starvation deadlock Ïóë çàáèò íèòÿìèD æäóùèìè ðåçóëüòàòà âû÷èñëåíèÿ Âû÷èñëåíèå â î÷åðåäèD íî åãî íåêîìó íà÷àòü ïóë çàáèò
  58. 58. Ñèíõðîíèçàöèÿ è íàñëåäîâàíèå Î÷åíü òðóäíî ñäåëàòü ýôôåêòèâíûé thread-safe êëàññ íà îñíîâå non-thread-safe áàçîâîãî. Ïðèäåòñÿ ïåðåãðóçèòü âñå äî åäèíîé îïåðàöèè  ò.÷. è äëèòåëüíûå, òÿæåëîâåñíûå Íå äàé áîã êàêèå-òî èç îïåðàöèé final Êàê ñ íàñëåäîâàíèåì: Design for inheritance or prohibit it Design for thread-safety
  59. 59. Ñèíõðîíèçàöèÿ è íàñëåäîâàíèå Ïàòòåðí Thread-safe interface: Ïîäåëèòå ìåòîäû êîìïîíåíòà íà 2 ÷àñòè (n—l èíòåðôåéñ C ðåàëèçàöèÿ Ñèíõðîíèçàöèÿ òîëüêî â ” èíòåðôåéñå“ ” Ðåàëèçàöèÿ“ âûçûâàåò òîëüêî ” ðåàëèçàöèþ“ Íàñëåäíèêè íå áåñïîêîÿòñÿ î ñèíõðîíèçàöèè Äîâîëüíî îáùèé ïàòòåðí ñèíõðîíèçàöèÿ → òðàíçàêöèÿ ÁÄD òðàíçàêöèÿ undoD F F F
  60. 60. Èäåìïîòåíòíûå îïåðàöèè foo();foo(); ∼ foo(); Òîãäà ìîæíî íå çàáîòèòüñÿ îá îãðàíè÷åíèè ÷èñëà âûçîâîâ foo() (íî foo() äîëæíà áûòü thread-safe). Îñîáåííî âàæíî â ðàñïðåäåëåííûõ è âåá-ñèñòåìàõ (ñ íåíàäåæíûì ïîäòâåðæäåíèåì âûçîâà foo()). ×àñòûé ïðèìåð ëåíèâàÿ èíèöèàëèçàöèÿ.
  61. 61. Èäåìïîòåíòíûå îïåðàöèè set.add(x) èäåìïîòåíòíà x.setFoo(foo) èäåìïîòåíòíà list.add(x) íå èäåìïîòåíòíà /buy.php?product_id=123 íå èäåìïîòåíòíà
  62. 62. Èäåìïîòåíòíûå îïåðàöèè Ïðèìåð äîñòèæåíèÿ èäåìïîòåíòíîñòè: Ïðèñâîèòü êàæäîìó âûçîâó îïåðàöèè óíèêàëüíûé id Åñëè òàêîé id óæå áûë ýòî äóáëü Àêòóàëüíî â âåáå.
  63. 63. Îñëàáëåíèå òðåáîâàíèé Èíîãäà îáåñïå÷èòü æåñòêèå èíâàðèàíòû öåëîñòíîñòè íåâîçìîæíî. Îíè ìîãóò íàðóøàòüñÿ èçâíå Åñòü âíåøíèå ïðîöåññûD íàðóøàþùèå öåëîñòíîñòü Îíè íàì íå ïîäêîíòðîëüíû ÍàïðèìåðX ñèíõðîíèçàöèÿ ôàéëîâD èçìåíÿåìûõ âíåøíèìè ïðîöåññàìè Èõ ñëèøêîì äîðîãî ïîääåðæèâàòü ÍàïðèìåðD áîëüøàÿ ðàñïðåäåëåííàÿ ñèñòåìà Ñèíõðîííîå ïðîòàëêèâàíèå èçìåíåíèÿ íà âñå ðåïëèêè ñëèøêîì äîëãî Ñ ó÷åòîì ïàäåíèé óçëîâ âñå åùå õóæå Ëåíü ïèñàòü ñëîæíûé êîä :)
  64. 64. Îòðèöàòåëüíàÿ îáðàòíàÿ ñâÿçü Ñóäÿ ïî âñåìó, îäèí èç ìîùíåéøèõ ïðèåìîâ ïðîåêòèðîâàíèÿ íåêîòîðûõ êëàññîâ ìíîãîçàäà÷íûõ ñèñòåì. Ñóòü: ” Ñîñòîÿíèå ñèñòåìû âñåãäà öåëîñòíî“ î÷åíü òðóäíî è íå âñåãäà íóæíî. ” Ñîñòîÿíèå ñèñòåìû âñå öåëîñòíåå è öåëîñòíåå“ ëåãêî îáåñïå÷èòü, ÷àñòî äîñòàòî÷íî. Äåëàåì ñèñòåìó ëèøü ñòðåìÿùåéñÿ ê ñîñòîÿíèþ öåëîñòíîñòè.
  65. 65. Îòðèöàòåëüíàÿ îáðàòíàÿ ñâÿçü Ïðèìåð ñòðóêòóðû: Ñèñòåìà ïåðèîäè÷åñêè ïðîñûïàåòñÿ è îñìàòðèâàåòñÿ Âû÷èñëÿåò, ÷åì ìèð îòëè÷àåòñÿ îò ” èäåàëà“ ÊàêèåEòî äàííûå ñ ÷åìEòî íå ñîãëàñîâàíû ÊàêèåEòî ãîòîâûå ê îáðàáîòêå äàííûå åùå íå îáðàáàòûâàþòñÿ ÊàêèåEòî äàííûå îáðàáàòûâàþòñÿ óæå ñëèøêîì äîëãîY íàâåðíîåD îáðàáîò÷èê óìåð F F F Âûïîëíÿåò äåéñòâèÿ.
  66. 66. Îòðèöàòåëüíàÿ îáðàòíàÿ ñâÿçü Ïëþñû ïîäõîäà ” ñèñòåìà êàê ñõîäÿùèéñÿ ïðîöåññ“: Îòðèöàòåëüíàÿ îáðàòíàÿ ñâÿçü Ïîñëåäñòâèÿ áîëüøèíñòâà ïðîáëåì ðàíî èëè ïîçäíî èñ÷åçíóòF Âûñîêàÿ ìîäóëüíîñòü Ñèñòåìà ðàñïàäàåòñÿ íà íàáîð ÷èñòî ëèíåéíûõ àâòîìàòîâE ” îáðàáîò÷èêîâ“F Î÷åíü ïðîñòàÿ îòëàäêà è òåñòèðîâàíèå Åñëè ÷òîEòî íå òàê ñèñòåìà ïðîñòî ïðèíÿëà íåïðàâèëüíîå ðåøåíèå â îäíîì èç ñîñòîÿíèéF ÌîæåòD ñàìî ðàññîñåòñÿD ìîæíî íå ôèêñèòü
  67. 67. Îòðèöàòåëüíàÿ îáðàòíàÿ ñâÿçü Âûñîêàÿ óñòîé÷èâîñòü Ñèñòåìà íåóÿçâèìà äëÿ ” ñìåðòåëüíûõ“ áàãîâ @™orrupted ñèíãëòîíûD óòå÷êè ðåñóðñîâAF Ñäåëàòü ñîñòîÿíèå persistentD ïåðåçàïóñêàòü ïðîöåññF Ãîòîâíîñòü ê ðàñïðåäåëåííîé ðàáîòå Ñäåëàòü ñîñòîÿíèå ãëîáàëüíî âèäèìûì è îáåñïå÷èòü ïðîñòåéøóþ áëîêèðîâêóF
  68. 68. Îòðèöàòåëüíàÿ îáðàòíàÿ ñâÿçü Ïðèìåíèìîñòü: Dataow-like çàäà÷è (äàííûå òåêóò ïî ñèñòåìå ñ ðÿäîì ýòàïîâ îáðàáîòêè) Ðåïëèêàöèÿ è ñèíõðîíèçàöèÿ Àðáèòðàæ ðåñóðñîâ è load balancing . . .
  69. 69. Eventual consistency Îòíîñèòñÿ ê ðàñïðîñòðàíåíèþ äàííûõ è èçìåíåíèé ïî ðàñïðåäåëåííîé ñèñòåìå. ” Êàæäîå èçìåíåíèå êîãäà-íèáóäü ñòàíåò âèäíî âñåé ñèñòåìå“. Âèäèìî, åäèíñòâåííàÿ ýôôåêòèâíàÿ ìîäåëü â äåéñòâèòåëüíî áîëüøèõ ñèñòåìàõ (Amazon, eBay è ò.ï.) CAP Theorem Choose any 2: Consistency: âñå óçëû âèäÿò ñèñòåìó îäèíàêîâî Availability: çàïðîñ ê æèâîìó óçëó îáÿçàòåëüíî ïîëó÷àåò îòâåò Partition tolerance: ëþáîå ñîîáùåíèå ìåæäó óçëàìè ìîæåò áûòü óòåðÿíî
  70. 70. Eventual consistency Consistency, Availability, Partition Tolerance. ACID 1 → BASE 2 ACID Atomicity Consistency Isolation Durability BASE Basically Available Soft state Eventually consistent Soft state The state . . . could be lost in a crash without permanent disruption of the service features being used. Clark, The design philosophy of the DARPA internet protocols 1 Êèñëîòà 2 Ùåëî÷ü
  71. 71. Further reading http://www.webperformancematters.com/journal/2007/8/ 21/asynchronous-architectures-4.html î ìàñøòàáèðîâàíèè â em—zonF Î÷åíü ïîëåçíûå ñîâåòûF http://www.infoq.com/interviews/ dan-pritchett-ebay-architecture î ìàñøòàáèðîâàíèè â ef—y http://roc.cs.berkeley.edu/ Èññëåäîâàòåëüñêèé ïðîåêò ‚e™overyEyriented gomputing Áîðîòüñÿ ñ ïîñëåäñòâèÿìè îøèáîêD ïîñêîëüêó èñêîðåíèòü âñå ïðè÷èíû íåâîçìîæíî Íåñêîëüêî îñíîâíûõ ïðèíöèïîâ @èçîëÿöèÿD èçáûòî÷íîñòüD undoD ñàìîäèàãíîñòèêàD ïåðåçàïóñêàåìîñòüA Î÷åíü ðàçóìíîD åñëè ïîäóìàòüF
  72. 72. Àáñòðàãèðîâàíèå Ìíîãîïîòî÷íóþ ïðîãðàììó íàìíîãî ëåã÷å íàïèñàòü è îòëàäèòü, åñëè â íåé íåò íè÷åãî, êðîìå ñàìîé ñóòè. Áàãè âûëåçàþò íà ïîâåðõíîñòü, íåò ñîáëàçíà ñêàçàòü  íàøåé çàäà÷å òàêàÿ ñèòóàöèÿ íåâîçìîæíà. Àëãîðèòìû ëåã÷å îòëàæèâàòü ïî îòäåëüíîñòè. Íå áëîêèðîâêà èíäåêñà íà ÷òåíèå èëè çàïèñü, à ïðîñòî áëîêèðîâêà íà ÷òåíèå èëè çàïèñü Íå î÷åðåäü e-mail'îâ, à îòêàçîóñòîé÷èâàÿ î÷åðåäü çàäà÷ Íå ïàðàëëåëüíûé ïîäñ÷åò ñëîâ, à MapReduce Íå ïàðàëëåëüíàÿ ôèëüòðàöèÿ ìàññèâà, à ParallelArray Ìîæåò îêàçàòüñÿ, ÷òî òàêàÿ øòóêà óæå åñòü.
  73. 73. Àáñòðàãèðîâàíèå À êàêèå øòóêè óæå åñòü? Îá ýòîì ïîçæå.
  74. 74. Àáñòðàãèðîâàíèå: ïðèìåð Ïðèâÿçêà ê âíåøíåé ñèñòåìå ñêà÷èâàíèÿ óðëîâ. Çàäàíèÿ ïèøóòñÿ â ôàéëû Âíåøíÿÿ ñèñòåìà èõ ïîäõâàòûâàåò Îòâåòû òîæå ïèøóòñÿ â ôàéëû Íàäî ïðåäîñòàâèòü àñèíõðîííûé API void loadPage(url, onOk, onError)
  75. 75. Àáñòðàãèðîâàíèå: ïðèìåð Devil in the details: Íå çàôëóäèòü ñèñòåìó (áëîêèðîâàòüñÿ, åñëè ìíîãî çàäàíèé ” â ïîëåòå“) Ñëåäèòü çà òàéìàóòàìè (äîëãî íå îòâå÷àåò → onError) Íå äîïóñêàòü ãîíîê ìåæäó îòâåòàìè è òàéìàóòàìè Áåðå÷ü íèòêó ñëåæåíèÿ çà îòâåòàìè (âûçûâàòü onOk,onError â îòäåëüíûõ íèòÿõ) Îáðàáàòûâàòü ðåäèðåêòû Îðãàíèçîâàòü ñèíõðîííûé shutdown
  76. 76. Àáñòðàãèðîâàíèå: ïðèìåð Áûëî: Íåòåñòèðóåìàÿ êàøà, äåëàþùàÿ âñå ñðàçó.
  77. 77. Àáñòðàãèðîâàíèå: ïðèìåð Ñòàëî: Ñåìàôîð äëÿ îãðàíè÷åíèÿ ÷èñëà çàäàíèé ” â ïîëåòå“ Àáñòðàêòíûé ïàòòåðí ” Stoppable“ Àáñòðàêòíûé ” áàò÷åð“ Àáñòðàêòíûé ” ïîëëåð“ Àáñòðàêòíûé ” òàéìàóòåð“ Âñ¼ ýëåìåíòàðíî òåñòèðóåòñÿ (íàøëèñü áàãè) Âñ¼ ïîëåçíî è ïîâòîðíî èñïîëüçóåìî
  78. 78. Àáñòðàãèðîâàíèå: ïðèìåð interface Stoppable { void stopSynchronously() throws InterruptedException; void stopEventually(); }
  79. 79. Àáñòðàãèðîâàíèå: ïðèìåð class BatcherT { Batcher(int periodMs); Stoppable start(); abstract void flush(T[] ts); void submit(T t); }
  80. 80. Àáñòðàãèðîâàíèå: ïðèìåð class PollerT { Poller(int periodMs); Stoppable start(); abstract @Nullable T poll(); abstract void process(@NotNull T t); }
  81. 81. Àáñòðàãèðîâàíèå: ïðèìåð class TimeouterT { Poller(int periodMs); Stoppable start(); void submit(T t, int timeoutMs); abstract void onTimedOut(T t); }
  82. 82. Àáñòðàãèðîâàíèå: ïðèìåð Èòîã: Èç áèçíåñ-ëîãèêè ïîëíîñòüþ ïðîïàë ìíîãîïîòî÷íûé êîä.
  83. 83. ×àñòü 2. Ïàòòåðíû è ïîäõîäû.
  84. 84. Ñîäåðæàíèå Êîððåêòíîñòü Ïðè÷èíû áàãîâ Äîêàçàòåëüñòâî êîððåêòíîñòè Óëó÷øåíèå êîððåêòíîñòè Ïàòòåðíû è ïîäõîäû Ïàðàëëåëèçì Concurrency Cutting edge Haskell Erlang .NET Clojure Çàêëþ÷åíèå Appendix Java memory model Ïðîèçâîäèòåëüíîñòü Òåñòèðîâàíèå è íàáëþäàåìîñòü
  85. 85. Ìîäåëè ìíîãîïîòî÷íûõ âû÷èñëåíèé Ïàðàëëåëèçì: MapReduce: Îãðîìíûå îáúåìû äàííûõ, ðàñïðåäåëåííàÿ îáðàáîòêà Fork/Join: Çàäà÷è ñ ðåêóðñèâíîé ñòðóêòóðîé Âåêòîðíûå ìîäåëè: huge-scale SIMD Êîíâåéåð / data ow . . . Concurrency: Message-passing (actor model) Event loop (message-passing ñ îäíèì / íåñêîëüêèìè îäèíàêîâûìè àêòîðàìè) ÑåðâåðàD áîëüøèíñòâî q…sEáèáëèîòåêD â òF÷F ƒwing Software Transactional Memory Àñèíõðîííîå ïðîãðàììèðîâàíèå
  86. 86. MapReduce Ñëèøêîì èçâåñòíî, ÷òîáû íà íåì îñòàíàâëèâàòüñÿ Ðåàëèçàöèÿ äëÿ Java: Hadoop
  87. 87. Fork/Join if(isSmall(problem)) { return solveSequentially(problem); } else { // Fork ListProblem subproblems = split(problem); ListResult res = parallelMap(solve, subproblems); // Join return combine(res); }
  88. 88. Fork/Join Ïðèìåð: Øàõìàòû. Ïðåäïðîñìîòð íà n øàãîâ. n==0 ⇒ îöåíèòü ïîçèöèþ Fork: Ïî ïîäçàäà÷å íà êàæäûé õîä Join: Âûáðàòü õîä ñ ñàìîé âûñîêîé îöåíêîé
  89. 89. Fork/Join Ïðèìåð: Èíòåãðèðîâàíèå. Èíòåðâàë ìàë ⇒ ïðîèíòåãðèðîâàòü âëîá Fork: ïî ïîäçàäà÷å íà îáå ïîëîâèíû èíòåðâàëà Join: ñëîæèòü ðåçóëüòàòû
  90. 90. Fork/Join Ïðèìåð: Óìíîæåíèå ìàòðèö: C+ = AB ( ò.÷. ïîèñê ïóòåé â ãðàôàõ è ò.ï.) A è B ìàëû ⇒ âëîá Fork: Ïîäåëèòü A íà âåðõ/íèç è B íà ëåâî/ïðàâî Join: Íè÷åãî, ïðîñòî äîæäàòüñÿ ðåçóëüòàòîâ Fork
  91. 91. Fork/Join
  92. 92. Fork/Join in JDK7 Ïðèìåðíî òàê. Îôèöèàëüíîãî îêîí÷àòåëüíîãî Javadoc äî ñèõ ïîð íåò. class Solver extends RecursiveAction { private final Problem problem; int result; protected void compute() { if (problem.size THRESHOLD) { result = problem.solveSequentially(); } else { int m = problem.size / 2; Solver left, right; left = new Solver(problem.subProblem(0, m)); right = new Solver(problem.subProblem(m, problem.size)); forkJoin(left, right); result = //get the result from left right } } } ForkJoinExecutor pool = new ForkJoinPool( Runtime.availableProcessors()); Solver solver = new Solver(new Problem()); pool.invoke(solver);
  93. 93. Âåêòîðíûå àëãîðèòìû Huge-scale SIMD: Ïðèìèòèâíûå îïåðàöèè îïåðèðóþò ñðàçó íàä áîëüøèìè ìàññèâàìè. Map: Ïðèìåíåíèå ôóíêöèè ê êàæäîìó ýëåìåíòó / ñêëåéêà N ìàññèâîâ ïî N-àðíîé îïåðàöèè Fold: Àññîöèàòèâíàÿ ñâåðòêà â ìîíîèäå. àññîöèàòèâíà: a (b c) = (a b) c u åäèíèöà : a u = u a = a fold u [x0, x1, . . . , xn] = u x0 x1 . . . xn Scan (Prex sum): Ïðîáåã (Ïðåôèêñíàÿ ñóììà) scan u [x0, x1, . . . , xn] = [u, u x0, u x0 x1, . . . , u . . . xn]
  94. 94. Âåêòîðíûå ìîäåëè Ïðåëåñòè: Ñâåðòêà ïàðàëëåëèçóåòñÿ: Óñêîðåíèå O(P/log P) íà P ïðîöåññîðàõ (â log P ðàç õóæå ëèíåéíîãî) Ïðîáåã òàê æå ïàðàëëåëèçóåòñÿ Óäèâèòåëüíî ìîùíûå è óíèâåðñàëüíûå îïåðàöèè
  95. 95. Ïðåôèêñíûå ñóììû ×òî ìîæíî ñäåëàòü ñâåðòêîé/ïðîáåãîì (ò.å. ïàðàëëåëüíî): sum,min,max,avg,. . . Radix sort, Quicksort Ñëîæåíèå äëèííûõ ÷èñåë Âûïóêëàÿ îáîëî÷êà Ìíîãèå àëãîðèòìû íà ãðàôàõ Ìíîãèå ðåêóððåíòíûå ïîñëåäîâàòåëüíîñòè n-ãî ïîðÿäêà Òðåõäèàãîíàëüíûå ñèñòåìû óðàâíåíèé . . .
  96. 96. Ïðåôèêñíûå ñóììû Îñîáåííî èíòåðåñíî, êàê ýòî äåëàåòñÿ. Áàçîâûå îïåðàöèè ïîâåðõ ïðîáåãà: Ðåêóððåíòíàÿ ïîñëåäîâàòåëüíîñòü 1ãî ïîðÿäêà Óïàêîâêà ìàññèâà Ñîðòèðîâêà ìàññèâà ïî 1-áèòíîìó ôëàãó (ðàçáèåíèå) Ñåãìåíòèðîâàííûé ïðîáåã (ïðîáåã ñî ñáðîñàìè)
  97. 97. Ïðåôèêñíûå ñóììû Óïàêîâêà ìàññèâà (pack, lter).
  98. 98. Ïðåôèêñíûå ñóììû Ñîðòèðîâêà ïî 1-áèòíîìó ôëàãó (ðàçáèåíèå, partition). Radixsort òðèâèàëåí.
  99. 99. Ïðåôèêñíûå ñóììû Ñåãìåíòèðîâàííûé ïðîáåã (Segmented scan). Ïîçâîëÿåò ðåàëèçîâàòü ðåêóðñèþ áåç ðåêóðñèè.
  100. 100. Ïðåôèêñíûå ñóììû  öåëîì êðàñèâûé, ìîùíûé, ïðîñòîé â ðåàëèçàöèè è íåîáû÷íûé âåêòîðíûé ÿçûê. ×àñòî èñïîëüçóþò íà GPU. http://sourceforge.net/projects/amino-cbbs/ ðåàëèçàöèÿ íà t—v— @ñîäåðæèò ìíîãî äðóãèõ ãîòîâûõ ïàðàëëåëüíûõ àëãîðèòìîâAF http://www.cs.cmu.edu/~blelloch/papers/Ble93.pdf ñòàòüÿ €re(x sums —nd their —ppli™—tionsX îáçîð òåõíèê è ïðèìåíåíèéF http://www.cs.cmu.edu/~blelloch/papers/Ble90.pdf †e™tor models for d—t—Ep—r—llel ™omputingD öåëàÿ êíèãà ïðî òî æåF Ñòðîæàéøå ðåêîìåíäóþF
  101. 101. ParallelArray New in JDK7. Ðåàëèçàöèÿ íåêîòîðûõ âåêòîðíûõ ïðèìèòèâîâ ïîâåðõ Fork/Join framework. Ñòàíäàðòíûå: Map, Zip, Filter, Fold (reduce), Scan (cumulate + precumulate), Sort Ïîèíòåðåñíåå: Ñå÷åíèå ïî äèàïàçîíó (withBounds), Ïåðåñòàíîâêà (replaceWithMappedIndex) Ôóíêöèîíàëüíûé äî ìîçãà êîñòåé API (ïîäàâëÿþùåå áîëüøèíñòâî ôóíêöèé ÔÂÏ) ÏðàâäàD áåç ôàíàòè÷íîãî ñëåäîâàíèÿ ôóíêöèîíàëüíîé ÷èñòîòå Ëåíèâûå îïåðàöèè Ñïëàâêà îïåðàöèé (fusion)
  102. 102. ParallelArray Ïðèìåð÷èê. ParallelArrayStudent students = new ParallelArrayStudent(fjPool, data); double bestGpa = students.withFilter(isSenior) .withMapping(selectGpa) .max(); public class Student { String name; int graduationYear; double gpa; } static final Ops.PredicateStudent isSenior = new Ops.PredicateStudent() { public boolean op(Student s) { return s.graduationYear == Student.THIS_YEAR; } }; static final Ops.ObjectToDoubleStudent selectGpa = new Ops.ObjectToDoubleStudent() { public double op(Student student) { return student.gpa; } };
  103. 103. Message-passing concurrency Ôàêòè÷åñêè åäèíñòâåííûé ïîäõîä â ðàñïðåäåëåííûõ ñèñòåìàõ. Âîîáùå íåò ðàçäåëÿåìîãî ñîñòîÿíèÿ Àêòîðû îáìåíèâàþòñÿ ñîîáùåíèÿìè Ó êàæäîãî àêòîðà åñòü mailbox (FIFO-î÷åðåäü ñîîáùåíèé) Îòñûëêà ñîîáùåíèé àñèíõðîííàÿ è íåáëîêèðóþùàÿ
  104. 104. Message-passing concurrency Íå ïàíàöåÿ: äåäëîêè åñòü (íî äðóãèå) Òåì íå ìåíåå, íàïèñàòü êîððåêòíóþ ïðîãðàììó ïðîùå Åñòü ôîðìàëüíûå ìîäåëè (CSP) ⇒ ïîääàåòñÿ âåðèôèêàöèè
  105. 105. Message-passing concurrency Ðåàëèçàöèè: Êó÷à ÿçûêîâ: MPI Termite Scheme Clojure: agents Î÷åíü èíòåðåñíàÿ è ìîùíàÿ âàðèàöèÿF he(nitely worth seeingF http://clojure.org/agents glojure is to ™on™urrent progr—mming —s t—v— w—s to yy€ Scala: actors Java: Kilim Haskell: CHP (Communicating Haskell Processes) È, êîíå÷íî, Erlang uiller fe—tureX ƒele™tive re™eive
  106. 106. Message-passing concurrency Kilim: Ëåãêîâåñíûå íèòè (1ìëí â ïîðÿäêå âåùåé, ñâåðõáûñòðîå ïåðåêëþ÷åíèå) Î÷åíü áûñòðûé message passing (óòâåðæäàåòñÿ, ÷òî 3x Erlang) Ïîñòïðîöåññèò áàéò-êîä (CPS transform äëÿ ìåòîäîâ, àííîòèðîâàííûõ @pausable).
  107. 107. Message-passing concurrency Further reading: http://kilim.malhar.net/ http://www.cl.cam.ac.uk/research/srg/opera/publications/ papers/kilim_ecoop08.pdf íàó÷íàÿ ñòàòüÿF Íå äëÿ ðîáêèõD íî ÷èòàòü ìîæíîF Ìíîãî èíòåðåñíûõ èäåéF http://eprints.kfupm.edu.sa/30514/1/30514.pdf îðèãèíàëüíàÿ êíèãà Òîíè Õîàðà ïðî gommuni™—ting ƒequenti—l €ro™esses òåîðåòè÷åñêàÿ îñíîâà mess—geEp—ssing
  108. 108. Event loop Âàðèàöèÿ íà òåìó message passing, íî íå ìíîãî âçàèìîäåéñòâóþùèõ àêòîðîâ, à îäèí (èëè íåñêîëüêî îäèíàêîâûõ) æèðíûé è âñåìîãóùèé. Ñåðâåðû (è accept, è select/poll/... ñþäà îòíîñÿòñÿ) GUI-ôðåéìâîðêè Ïðåëåñòè: Ýòî íå ôðåéìâîðê, íî ïàòòåðí: ëåãêî ðåàëèçîâàòü è èñïîëüçîâàòü äàæå íà ìèêðîóðîâíå Ê íåìó ñâîäèòñÿ êó÷à çàäà÷ Î÷åíü ëåãêî ïèøåòñÿ Áîëüøèíñòâî ìíîãîïîòî÷íûõ ïðîáëåì îòñóòñòâóþò
  109. 109. Event loop private BlockingQueueOurEvent events = new LinkedBlockingQueueOurEvent(); void mainLoop() { while(true) { processEvent(events.poll()); } } public class OurEvent {...}
  110. 110. Software Transactional Memory Òðàíçàêöèè íà óðîâíå ïàìÿòè; àòîìàðíûå êóñêè êîäà. Ïîëíîöåííûé commit/rollback, ïîëíàÿ àòîìàðíîñòü Òðàíçàêöèè ïîâòîðÿåìû retry ïðè êîììèòåD åñëè èçâíå èçìåíåíà ïðî÷òåííàÿ ïåðåìåííàÿ Òðàíçàêöèîííûå ïðîãðàììû êîìáèíèðóåìû!  îòëè÷èå îò sh—red st—te @ïðàâèëüíîCïðàâèëüíî=ïðàâèëüíîA Íå äîëæíî áûòü íèêàêèõ ïîáî÷íûõ ýôôåêòîâ, êðîìå îáðàùåíèé ê òðàíçàêöèîííîé ïàìÿòè
  111. 111. Software Transactional Memory Ïñåâäîêîä: // Insert a node into a doubly-linked list atomically atomic { newNode-prev = node; newNode-next = node-next; node-next-prev = newNode; node-next = newNode; }
  112. 112. Software Transactional Memory Ïñåâäîêîä (âïåðâûå ïðåäëîæåíî â ðåàëèçàöèè â Haskell): atomic { if (queueSize 0) { remove item from queue and use it } else { retry } } retry ïåðåçàïóñêàåò òðàíçàêöèþ â ìîìåíò, êîãäà èçìåíèòñÿ îäíà èç ïðî÷èòàííûõ åþ ïåðåìåííûõ.
  113. 113. Software Transactional Memory Ðåàëèçàöèè: Haskell: ïîëíîöåííàÿ è áåçîïàñíàÿ ïîääåðæêà Clojure: ïîëíîöåííàÿ è íåáåçîïàñíàÿ ïîääåðæêà Java: Deuce, JSTM, . . . Ìíîãî áèáëèîòåê äëÿ C è C++, â ò.÷. äàæå êîìïèëÿòîðû ñ êëþ÷åâûì ñëîâîì atomic Íå çíàþD èñïîëüçóþò ëè èõ
  114. 114. Software Transactional Memory Further reading: http://research.microsoft.com/Users/simonpj/papers/stm/ stm.pdf gompos—˜le wemory „r—ns—™tionsF http: //themonadreader.files.wordpress.com/2010/01/issue15.pdf Æóðíàë won—dF‚e—der sssue ISD ñîäåðæèò ñòàòüþ smplementing ƒ„w in pure r—skellD èíòåðåñíîå îáñóæäåíèå âîïðîñîâ ðåàëèçàöèè ƒ„wF
  115. 115. Àñèíõðîííîå ïðîãðàììèðîâàíèå Íàáèðàåò îáîðîòû áëàãîäàðÿ âåáó (AJAX) è áîëüøèì ðàñïðåäåëåííûì ñèñòåìàì, ãäå ñèíõðîííûé RPC ñëèøêîì äîðîã. Quite a challenge.
  116. 116. Àñèíõðîííîå ïðîãðàììèðîâàíèå Ñèíõðîííûé API: interface API { Answer compute(Question request) throws Whoops; } Àñèíõðîííûé API: interface API { void compute(Question request, {Answer = void} onReady, {Whoops = void} onWhoops) }
  117. 117. Àñèíõðîííîå ïðîãðàììèðîâàíèå Ïðè÷èíû: Áëîêèðóþùèå âûçîâû íåóäîáíû èëè íå ïîääåðæèâàþòñÿ eteˆ q…s @ ” àñèíõðîííî ïîëó÷èòü ðåçóëüòàò äèàëîãà“ è òFïFA Àñèíõðîííûé API äîïóñêàåò áîëåå ýôôåêòèâíóþ ðåàëèçàöèþ Àñèíõðîííûé ââîäEâûâîä Àñèíõðîííûé äîñòóï ê õðàíèëèùàì äàííûõ F F F Àêòèâíàÿ ñòîðîíà @ñåðâåðD ñåòåâîé äðàéâåð ÎÑ F F F A ìîæåò ðåøàòüD êîãäà è â êàêîì ïîðÿäêå îòâå÷àòü íà çàïðîñû
  118. 118. Àñèíõðîííîå ïðîãðàììèðîâàíèå Ïðîáëåìû: Íåëèíåéíûé ïîòîê èñïîëíåíèÿ Î÷åíü íåóäîáíî îòëàæèâàòü Ïîøàãîâîå âûïîëíåíèå â îòëàä÷èêå íå ðàáîòàåò Íåò àíàëîãîâ ïðèâû÷íûõ êîíñòðóêöèé óïðàâëåíèÿ (öèêëû, try..finally . . . ) Äàæå ñýìóëèðîâàòü èõ íåëåãêî  áîëüøèíñòâå ßÏ àñèíõðîííûé êîä êðàéíå ãðîìîçäîê
  119. 119. Àñèíõðîííîå ïðîãðàììèðîâàíèå public void requestInit() { AdminConsoleService.App.getInstance().getLoadGeneratorServersInfo( new AcAsyncCallbackListServerInfo() { public void doOnSuccess(final ListServerInfo loadGenerators) { AdminConsoleService.App.getInstance().getApplicationServersInfo( new AcAsyncCallbackListServerInfo() { public void doOnSuccess(ListServerInfo appServers) { init(appServers, loadGenerators); } }); } }); } (c) ru_java.
  120. 120. Àñèíõðîííîå ïðîãðàììèðîâàíèå Êàê æå áûòü?
  121. 121. Àñèíõðîííîå ïðîãðàììèðîâàíèå Êàê æå áûòü? Âñïîìèíàåì óðîêè ôóíêöèîíàëüíîãî ïðîãðàììèðîâàíèÿ. Èçáàâèòüñÿ îò ñèíòàêñè÷åñêîãî ìóñîðà Àñèíõðîííûå çíà÷åíèÿ ïåðâîêëàññíûå îáúåêòû @ñìF äàëååA Íóæåí ÿçûê ñ çàìûêàíèÿìèF ƒorry guysF Ðåàëèçîâàòü ñòðóêòóðû óïðàâëåíèÿ Íå ñîéòè ñ óìà îò ñëîæíîñòè
  122. 122. Àñèíõðîííîå ïðîãðàììèðîâàíèå Êàê æå áûòü? Âñïîìèíàåì óðîêè ôóíêöèîíàëüíîãî ïðîãðàììèðîâàíèÿ. Èçáàâèòüñÿ îò ñèíòàêñè÷åñêîãî ìóñîðà Ðåàëèçîâàòü ñòðóêòóðû óïðàâëåíèÿ Öèêëû ÷åðåç ðåêóðñèþ Ýìóëÿöèÿ õâîñòîâûõ âûçîâîâ Âñå ýòî ñòîèò àáñòðàãèðîâàòü â ” êîìáèí¡àòîðíóþ áèáëèîòåêó“ Íå ñîéòè ñ óìà îò ñëîæíîñòè
  123. 123. Àñèíõðîííîå ïðîãðàììèðîâàíèå Êàê æå áûòü? Âñïîìèíàåì óðîêè ôóíêöèîíàëüíîãî ïðîãðàììèðîâàíèÿ. Èçáàâèòüñÿ îò ñèíòàêñè÷åñêîãî ìóñîðà Ðåàëèçîâàòü ñòðóêòóðû óïðàâëåíèÿ Íå ñîéòè ñ óìà îò ñëîæíîñòè Öåëûé êëàññ ïðîáëåìD ñïåöèôè÷íûõ äëÿ ýòîãî ïîäõîäà Áîëüøèíñòâî ñâÿçàíî ñ mut—˜le st—te
  124. 124. Àñèíõðîííîå ïðîãðàììèðîâàíèå Îñíîâíàÿ èäåÿ: interface AsyncT { void run(CallbackT onOk, CallbackThrowable onError); } Ýòè îáúåêòû êîìáèíèðóåìû.
  125. 125. Àñèíõðîííîå ïðîãðàììèðîâàíèå Ó÷èìñÿ ó .NET âîîáùå è F# â ÷àñòíîñòè. let AsyncHttp(url:string) = async { // Create the web request object let req = WebRequest.Create(url) // Get the response, asynchronously let! rsp = req.GetResponseAsync() // Grab the response stream and a reader. Clean up when we're done use stream = rsp.GetResponseStream() use reader = new System.IO.StreamReader(stream) // synchronous read-to-end return reader.ReadToEnd() } Ýòî íàçûâàåòñÿ ” asynchronous workows“. Workow êðàñèâûé ñèíîíèì äëÿ ñëîâà ” Ìîíàäà“ (google://workow, monad). http://blogs.msdn.com/dsyme/archive/2007/10/11/ introducing-f-asynchronous-workflows.aspx
  126. 126. Àñèíõðîííîå ïðîãðàììèðîâàíèå class AsyncPrimitives { AsyncT succeed(T value) {...} AsyncT failwith(Throwable error) {...} AsyncU bind(AsyncT at, FuncT,AsyncU fau) {...} } Ýòîãî äîñòàòî÷íî äëÿ áîëüøèíñòâà ñòðóêòóð óïðàâëåíèÿ 3. Ýòî íàçûâàåòñÿ ” ìîíàäà“. 3 Ïðè ïîääåðæêå îïòèìèçàöèè õâîñòîâûõ âûçîâîâ
  127. 127. Àñèíõðîííîå ïðîãðàììèðîâàíèå Ìîíàäû ïðîíèêëè â ìåéíñòðèì: ó C# òåïåðü òîæå ó÷èìñÿ (LINQ). var requests = new[] { WebRequest.Create(http://www.google.com/), WebRequest.Create(http://www.yahoo.com/), WebRequest.Create(http://channel9.msdn.com/) }; http://www.aboutcode.net/2008/01/14/Async+WebRequest+ Using+LINQ+Syntax.aspx
  128. 128. Àñèíõðîííîå ïðîãðàììèðîâàíèå Ìîíàäû ïðîíèêëè â ìåéíñòðèì: ó C# òåïåðü òîæå ó÷èìñÿ (LINQ). var pages = from request in requests select from response in request.GetResponseAsync() let stream = response.GetResponseStream() from html in stream.ReadToEndAsync() select new { html, response }; http://www.aboutcode.net/2008/01/14/Async+WebRequest+ Using+LINQ+Syntax.aspx
  129. 129. Àñèíõðîííîå ïðîãðàììèðîâàíèå Ìîíàäû ïðîíèêëè â ìåéíñòðèì: ó C# òåïåðü òîæå ó÷èìñÿ (LINQ). foreach (var page in pages) { page(d = { Console.WriteLine(d.response.ResponseUri.ToString()); Console.WriteLine(d.html.Substring(0, 40)); Console.WriteLine(); }); } http://www.aboutcode.net/2008/01/14/Async+WebRequest+ Using+LINQ+Syntax.aspx ÌîðàëüX Ïîçíàéòå ìîíàäû ñòàíåò ëåã÷å ïèñàòü àñèíõðîííûé êîäF
  130. 130. Àñèíõðîííîå ïðîãðàììèðîâàíèå Further reading: Î÷åíü èíòåðåñíûé ïîäõîä ñ èñïîëüçîâàíèåì yield return: http://tomasp.net/blog/csharp-async.aspxF ‡es hyer îáúÿñíåíèå ìîíàäû gont íà g5X http://blogs.msdn. com/wesdyer/archive/2008/01/11/the-marvels-of-monads.aspx ×òî òàêîå êîìáèíàòîðíàÿ áèáëèîòåêàX http://fprog.ru/2009/issue3D ñòàòüÿ ” Ýëåìåíòû ôóíêöèîíàëüíûõ ÿçûêîâ“ Àñèíõðîííûå êîìáèíàòîðû íà t—v—X http://spbhug.folding-maps.org/wiki/EugeneKirpichovD ñëàéäû ïðî t—v— è p€F
  131. 131. Further reading Ðàçíûå ïàòòåðíû ìíîãîïîòî÷íîãî è ðàñïðåäåëåííîãî ïðîãðàììèðîâàíèÿ. Î÷åíü ìíîãî è èíòåðåñíî. http://www.cs.wustl.edu/~schmidt/patterns-ace.html http: //parlab.eecs.berkeley.edu/wiki/patterns/patterns åùå êðó÷å
  132. 132. Ñîäåðæàíèå Êîððåêòíîñòü Ïðè÷èíû áàãîâ Äîêàçàòåëüñòâî êîððåêòíîñòè Óëó÷øåíèå êîððåêòíîñòè Ïàòòåðíû è ïîäõîäû Ïàðàëëåëèçì Concurrency Cutting edge Haskell Erlang .NET Clojure Çàêëþ÷åíèå Appendix Java memory model Ïðîèçâîäèòåëüíîñòü Òåñòèðîâàíèå è íàáëþäàåìîñòü
  133. 133. Cutting edge ×òî óìååò Haskell: Âñå ïîáî÷íûå ýôôåêòû êîíòðîëèðóþòñÿ Íåò íåêîíòðîëèðóåìûõ ïðîáëåì èç-çà èõ íàëè÷èÿ Ïîçâîëÿåò íåìûñëèìûå â äðóãèõ ÿçûêàõ âåùè
  134. 134. Cutting edge ×òî óìååò Haskell: Ñàìûå áûñòðûå â ìèðå ëåãêîâåñíûå íèòè è ïðèìèòèâû ñèíõðîíèçàöèè I ìåñòî íà v—ngu—ge ƒhootoutD THx áûñòðåå íàòèâíûõ …˜untuD Sõ áûñòðåå irl—ng3 Ïàðàëëåëüíûå ñòðàòåãèè Ïðîñòûå ïàðàëëåëüíûå âû÷èñëåíèÿX íåò àíàëîãîâ â äðóãèõ ÿçûêàõ Data Parallel Haskell Àâòîìàòè÷åñêè ðàñïàðàëëåëèâàåìûå âåêòîðíûå âû÷èñëåíèÿ Òðàíçàêöèîííàÿ ïàìÿòü Ðàáîòà â íàïðàâëåíèè GPU Ìîùíûå áèáëèîòåêè
  135. 135. Ëåãêîâåñíûå íèòè Nothing special, ïðîñòî î÷åíü áûñòðûå è ïî÷òè 0 ñèíòàêñè÷åñêîãî îâåðõåäà. C++0x futures/promises and more â 60 ñòðîê.
  136. 136. Ïàðàëëåëüíûå ñòðàòåãèè Ëåíèâîñòü ïîçâîëÿåò îòäåëèòü àëãîðèòì è ñïîñîá ðàñïàðàëëåëèâàíèÿ. Ðåçóëüòàò àëãîðèòìà ñòðóêòóðà, ïîëíàÿ ” îáåùàíèé“. Îáåùàíèÿ ” èñïîëíÿþòñÿ“ (ôîðñèðóþòñÿ) ñ ïîìîùüþ ñòðàòåãèè. Ñòðàòåãèÿ ýòî îáûêíîâåííàÿ, ïðîñòàÿ ôóíêöèÿ. Èäåÿ ÿäåðíàÿ. Ýòî ìîæíî ðåàëèçîâàòü è íà Java, åñëè
  137. 137. Ïàðàëëåëüíûå ñòðàòåãèè Íàïðèìåð, ñòðàòåãèÿ ” ïàðàëëåëüíî ôîðñèðîâàòü âñå ýëåìåíòû ñïèñêà“: parList :: Strategy a - Strategy [a] parList strat [] = () parList strat (x:xs) = strat x `par` (parList strat xs)
  138. 138. Data Parallel Haskell Âåêòîðèçàòîð (òðàíñëèðóåò äàæå ðåêóðñèâíûå ôóíêöèè â âåêòîðíûå îïåðàöèè) Áèáëèîòåêà ïàðàëëåëüíûõ âåêòîðíûõ îïåðàöèé dotp_double :: [:Double:] - [:Double:] - Double dotp_double xs ys = sumP [:x * y | x - xs | y - ys:] smMul :: [:[:(Int,Float):]:] - [:Float:] - Float smMul sm v = sumP [: svMul sv v | sv - sm :] http://research.microsoft.com/en-us/um/people/simonpj/ papers/ndp/NdpSlides.pdf ñëàéäû
  139. 139. Data Parallel Haskell sort :: [:Float:] - [:Float:] sort a = if (length a = 1) then a else sa!0 +++ eq +++ sa!1 where m = a!0 lt = [: f | f-a, fm :] eq = [: f | f-a, f==m :] gr = [: f | f-a, fm :] sa = [: sort a | a - [:lt,gr:] :] Âåêòîðèçóåòñÿ è ïàðàëëåëèçóåòñÿ.
  140. 140. Repa Regular, shape-polymorphic, parallel arrays in Haskell. The Haskell code transparently makes use of multicore hardware Ñäåëàíî ãðóïïîé Ìàíóýëÿ ×àêðàâàðòè ýòî îäèí èç êðóòåéøèõ èìïëåìåíòîðîâ Õàñêåëëà. http://justtesting.org/ regular-shape-polymorphic-parallel-arrays-in
  141. 141. Òðàíçàêöèîííàÿ ïàìÿòü transfer :: Account - Account - Int - IO () transfer from to amount = atomically do deposit to amount withdraw from amount
  142. 142. Òðàíçàêöèîííàÿ ïàìÿòü check True = return () check False = retry limitedWithdraw :: Account - Int - STM () limitedWithdraw acc amount = do bal - readTVar acc check (amount = 0 || amount = bal) writeTVar acc (bal - amount) ×åòêîå ðàçäåëåíèå ìåæäó: IO êîä ñ ïðîèçâîëüíûìè ïîáî÷íûìè ýôôåêòàìè STM êîä, åäèíñòâåííûé ýôôåêò êîòîðîãî ðàáîòà ñ òðàíçàêöèîííîé ïàìÿòüþ atomically :: STM t - IO t (íàîáîðîò íåëüçÿ)
  143. 143. Erlang Ñâÿçü ïðîöåññîâ òîëüêî ÷åðåç îáìåí ñîîáùåíèÿìè. Selective receive (èçáèðàòåëüíàÿ âûáîðêà èç mailbox). Ìîùíàÿ ôè÷àF Ïðîçðà÷íàÿ ðàñïðåäåëåííîñòü. Î÷åíü ýôôåêòèâíàÿ ðåàëèçàöèÿ íèòåé è message passing. Î÷åíü êðóòàÿ è ïðîäóìàííàÿ èíôðàñòðóêòóðà. Î÷åíü ïðîñòîé ÿçûê. Àêòèâíî ïðèìåíÿåòñÿ â èíäóñòðèè (â ò.÷. Amazon, Facebook, Yahoo, . . . ). http://spbhug.folding-maps.org/wiki/Erlang ñàìîïèàð YA
  144. 144. F# Asynchronous workows: óæå ðàññìîòðåëè.
  145. 145. C# Asynchronous LINQ (ìîæíî ñäåëàòü ñàìîìó: LINQ = ìîíàäû) Óæå ðàññìîòðåëè Parallel LINQ
  146. 146. Parallel LINQ (PLINQ) IEnumerableT, IParallelEnumerableT AsParallel http://msdn.microsoft.com/en-us/magazine/cc163329.aspx
  147. 147. Parallel LINQ (PLINQ) IEnumerableT data = ...; var q = from x in data.AsParallel() where p(x) orderby k(x) select f(x); foreach (var e in q) a(e); Òðàíñëèðóåòñÿ â êîìáèíàöèþ ParallelEnumerable.{Select,Where,OrderBy} è ò.ï.
  148. 148. Parallel LINQ (PLINQ) IEnumerableT leftData = ..., rightData = ...; var q = from x in leftData.AsParallel() join y in rightData on x.a == y.b select f(x, y);
  149. 149. Clojure Clojure is to concurrent programming as Java was to OOP Áèáëèîòåêà ÷èñòî ôóíêöèîíàëüíûõ ñòðóêòóð äàííûõ 4 ìåõàíèçìà concurrency: Atoms, Vars, Agents, Refs Âñå îíè îïåðèðóþò íàä immutable çíà÷åíèÿìè è ÷èñòûìè ôóíêöèÿìè fe™—use this is the w—y to goF
  150. 150. Atoms Áîëåå èëè ìåíåå îáû÷íûå atomic ïåðåìåííûå. (swap! atom f) ” Àòîìàðíî çàìåíèòü x íà f (x), âåðíóòü ñòàðûé x (compare-and-exchange)“ f îáÿçàíà áûòü ÷èñòîé: åå ìîãóò âûçâàòü íåñêîëüêî ðàç http://clojure.org/atoms
  151. 151. Vars Thread-local, dynamically scoped ïåðåìåííûå. (def x 0) îáúÿâèòü x ñ ãëîáàëüíûì çíà÷åíèåì ïî óìîë÷àíèþ 0. x ïðî÷èòàòü çíà÷åíèå x. (set! x 5) ïðèñâîèòü x = 5 â ðàìêàõ òåêóùåé íèòè. (binding [x 5] (do-something)) âûïîëíèòü do-something, ïîëàãàÿ x = 5 â ðàìêàõ òåêóùåé íèòè. http://clojure.org/vars
  152. 152. Agents Àñèíõðîííî èçìåíÿåìûå ïåðåìåííûå. (agent 0) àãåíò ñ íà÷àëüíûì çíà÷åíèåì 0 (deref x) òåêóùåå çíà÷åíèå (send x f) àñèíõðîííî çàìåíèòü x íà f (x) (await x) äîæäàòüñÿ îêîí÷àíèÿ âñåõ äåéñòâèé íàä àãåíòîì (set-validator x f) ïîâåñèòü âàëèäàòîð ñîñòîÿíèÿ (add-watch x f) ïîâåñèòü ñëóøàòåëÿ http://clojure.org/agents
  153. 153. Refs Òðàíçàêöèîííàÿ ïàìÿòü (STM). Äîâîëüíî îáû÷íàÿ Òðàíçàêöèè äîëæíû áûòü áåç ïîáî÷íûõ ýôôåêòîâ Ëþáîïûòíî: (commute x f): çàìåíèòü x íà f (x), ïðåäïîëàãàÿ ÷òî f êîììóòèðóåò ñ îñòàëüíûìè. ÍàïðèìåðD (commute counter inc) ïîäîéäåò Ðàáîòàåò ñëåãêà áûñòðååD ÷åì äðóãèå ôóíêöèèEìóòàòîðû http://clojure.org/refs
  154. 154. Ñîäåðæàíèå Êîððåêòíîñòü Ïðè÷èíû áàãîâ Äîêàçàòåëüñòâî êîððåêòíîñòè Óëó÷øåíèå êîððåêòíîñòè Ïàòòåðíû è ïîäõîäû Ïàðàëëåëèçì Concurrency Cutting edge Haskell Erlang .NET Clojure Çàêëþ÷åíèå Appendix Java memory model Ïðîèçâîäèòåëüíîñòü Òåñòèðîâàíèå è íàáëþäàåìîñòü
  155. 155. ×òî áûëî Êëàññèôèêàöèÿ ìíîãîïîòî÷íûõ ïðîãðàìì Ôîðìàëüíûå ìåòîäû (LTL) è òóëû (SPIN,JPF,CheckThread) Êîððåêòíîñòü: èíêàïñóëÿöèÿ, âûñîêîóðîâíåâûå îïåðàöèè, ôàêòîðèçàöèÿ, äåäëîêè, àòîìàðíûå è èäåìïîòåíòíûå îïåðàöèè, îòðèöàòåëüíàÿ îáðàòíàÿ ñâÿçü Ìåòîäèêè: fork/join, âåêòîðíûå àëãîðèòìû, message-passing, event-driven, STM, àñèíõðîííîå ïðîãðàììèðîâàíèå Haskell: ëåãêèå íèòè, ïàðàëëåëüíûå ñòðàòåãèè, âåêòîðèçàöèÿ, STM Erlang: ìîùíàÿ èíôðàñòðóêòóðà Clojure: Atoms, Vars, Agents, Refs C#: PLINQ
  156. 156. The end Ñïàñèáî! Âîïðîñû?
  157. 157. Ñîäåðæàíèå Êîððåêòíîñòü Ïðè÷èíû áàãîâ Äîêàçàòåëüñòâî êîððåêòíîñòè Óëó÷øåíèå êîððåêòíîñòè Ïàòòåðíû è ïîäõîäû Ïàðàëëåëèçì Concurrency Cutting edge Haskell Erlang .NET Clojure Çàêëþ÷åíèå Appendix Java memory model Ïðîèçâîäèòåëüíîñòü Òåñòèðîâàíèå è íàáëþäàåìîñòü
  158. 158. Java Memory Model Ãðóáî: Íàáîð àêñèîì î òîì, êàêèå ïðîèñøåñòâèÿ â ïàìÿòè êîìó è êîãäà âèäèìû. ×òîáû êîìïèëÿòîð ìîã âûïîëíÿòü îïòèìèçàöèè Ïåðåóïîðÿäî÷åíèåD óäàëåíèå äîõëîãî êîäà F F F ×òîáû ìîæíî áûëî ýôôåêòèâíî èñïîëüçîâàòü êýøè, îñîáåííî â ìíîãîïðîöåññîðíûõ ñèñòåìàõ.
  159. 159. Ïðèìåð private int x, y; void foo() { x = 5; y = 7; } void bar() { if(x==5) { // Íåâåðíî, ÷òî y==7 } }
  160. 160. nal ïîëÿ è JMM Ïðèìåð public final class Foo { private int x; Foo(int x) {this.x = x;} int getX() {return x; } } Íå thread-safe! x äîëæåí áûòü nal.
  161. 161. Java Memory Model Áîëåå òî÷íî: Íàáîð àêñèîì î òîì, êàêèå íàáëþäåíèÿ ðåçóëüòàòîâ ïîñëåäîâàòåëüíîñòè äåéñòâèé â ïàìÿòè âîçìîæíû. Öåëè: Áåçîïàñíîñòü Áåçîïàñíàÿ èíèöèàëèçàöèÿ Èíòóèòèâíîñòü Ýôôåêòèâíàÿ ðåàëèçóåìîñòü
  162. 162. Java Memory Model Âëèÿþùèå ôàêòîðû: synchronized volatile final
  163. 163. Java Memory Model Îñíîâíûå ïîíÿòèÿ: Äåéñòâèå Îáðàùåíèå ê ðàçäåëÿåìûì ïåðåìåííûì ÂõîäGâûõîä èç ìîíèòîðà ÇàïóñêGîæèäàíèå íèòåé Âèäèìîñòü Îòíîøåíèå happens-before Æèçíü I íèòè óïîðÿäî÷åíà Æèçíü I ìîíèòîðà óïîðÿäî÷åíà Æèçíü I vol—tile ïåðåìåííîé óïîðÿäî÷åíà
  164. 164. ×òî âñå-òàêè äåëàåò volatile? ×òåíèå îäíîé volatile ïåðåìåííîé ïî÷òè òî÷êà ñèíõðîíèçàöèè. class VolatileExample { int x = 0; volatile boolean v = false; public void writer() { x = 42; v = true; } public void reader() { if (v == true) { /* x==42 */ } } }
  165. 165. ×òî âñå-òàêè äåëàåò nal? Ïîñëå êîíñòðóèðîâàíèÿ final ïîëÿ âèäèìû. Âèäèìû òàêæå îáúåêòû, äîñòóïíûå ÷åðåç íèõ Ññûëêà íà îáúåêò íå äîëæíà óòåêàòü èç êîíñòðóêòîðà Ðåãèñòðàöèÿ ëèñòåíåðîìD ïðèñâàèâàíèå ñòàòè÷åñêîãî ïîëÿFFF Äåëàéòå ýòî ïîñëå êîíñòðóèðîâàíèÿF
  166. 166. Ïðîèçâîäèòåëüíîñòü ×òî òîðìîçèò? Æäóùèå íèòè Çàõâàò (äàæå óñïåøíûé) áëîêèðîâîê Ïåðåêëþ÷åíèå êîíòåêñòîâ
  167. 167. Ïðîèçâîäèòåëüíîñòü ×òî äåëàòü? Íå æäàòü è íå áëîêèðîâàòüñÿ Íå ïåðåêëþ÷àòüñÿ
  168. 168. Óìåíüøåíèå áëîêèðîâîê Êàê íå æäàòü? Èñïîëüçîâàòü íåáëîêèðóþùèå àëãîðèòìû è îïåðàöèè Óâåëè÷èòü ãðàíóëÿðíîñòü áëîêèðîâîê ÀíòîíèìX Îäèí ìîíèòîð íà âñþ ïðîãðàììó Èñïîëüçîâàòü àëãîðèòìû, áëîêèðóþùèå íå âñåõ ‚e—der‡ritervo™k
  169. 169. Íåáëîêèðóþùèå àëãîðèòìû è îïåðàöèè Áàçèñ: get, set, getAndSet boolean compareAndSet(expect, update) (CAS) Ïîìåíÿòü ñ expect íà upd—te Åñëè íå expe™t çíà÷èòD ìû ïðîçåâàëèD êàê êòîEòî ïîìåíÿë èç äðóãîé íèòè Íàäî ïåðåçàïóñòèòü êóñîê àëãîðèòìà â íàäåæäåD ÷òî òåïåðü îáîéäåòñÿ áåç êîëëèçèé addAndGet, getAndAdd, . . .
  170. 170. Íåáëîêèðóþùèå àëãîðèòìû è îïåðàöèè Ñðåäñòâà â Java: java.util.concurrent.atomic AtomicInteger, AtomicLong AtomicReference, AtomicStampedReference (ìàëîèçâåñòíî) AtomicIntegerArray, Long, Reference
  171. 171. Àòîìàðíûå îïåðàöèè Ïðèìåð àëãîðèòìà íà CAS: public class ConcurrentStackE { AtomicReferenceNodeE head = new AtomicReferenceNodeE(); public void push(E item) { NodeE newHead = new NodeE(item); NodeE oldHead; do { oldHead = head.get(); newHead.next = oldHead; } while (!head.compareAndSet(oldHead, newHead)); } public E pop() { ... } } http://www.ibm.com/developerworks/java/library/j-jtp04186/ index.html
  172. 172. Íåáëîêèðóþùèå êîíòåéíåðû Ãîòîâûå íåáëîêèðóþùèå ñòðóêòóðû äàííûõ (New in JDK6): ConcurrentSkipListMap ConcurrentSkipListSet Ïðåëåñòè: Èòåðàòîðû íèêîãäà íå áðîñàþò CME
  173. 173. Óìåíüøåíèå ãðàíóëÿðíîñòè áëîêèðîâîê Áëîêèðóéòå íå âñ¼ Áëîêèðóéòå íå âñåõ
  174. 174. Óìåíüøåíèå ãðàíóëÿðíîñòè áëîêèðîâîê Áëîêèðóéòå íå âñ¼: Åñëè íàäî çàùèòèòü áîëüøóþ ñòðóêòóðó äàííûõ, íî ìåíÿþòñÿ òîëüêî åå êóñêè çàùèùàéòå êóñêè èëè ãðóïïû êóñêîâ. Ïðèìåð: ConcurrentHashMap (new in JDK6). Òåõíèêà lock striping. ×òåíèå íåáëîêèðóþùåå Çàïèñü áëîêèðóþùàÿ â 1/k ñëó÷àåâ, ãäå k íàñòðàèâàåòñÿ Ðåêîìåíäóåòñÿ k ≈ ÷èñëî íèòåéEïèñàòåëåé k áëîêèðîâîê çàùèùàþò k êóñêîâ õýø-òàáëèöû Èòåðàòîðû òàêæå íå áðîñàþò CME
  175. 175. Reader/Writer lock Áëîêèðóéòå íå âñåõ: ×òåíèå ñîâìåñòèìî ñ ÷òåíèåì, íî íå ñ çàïèñüþ. Áûâàþò ðàçíûå: Readers-preference Writers-preference Arrival-order . . . Êëàññ ReentrantReadWriteLock. Ðåàëèçóåò ïðèìåðíî arrival-order. Åñëè åñòü æäóùèé ïèñàòåëü íîâûå ÷èòàòåëè òîëüêî ïîñëå íåãî.
  176. 176. Ïåðåêëþ÷åíèå êîíòåêñòîâ Êàê ïîìåíüøå ïåðåêëþ÷àòü êîíòåêñòû? Èìåòü ïîìåíüøå íèòåé ÍàïðèìåðD îäíó @iventEdrivenA Ïîáîëüøå àñèõðîííîñòè
  177. 177. Ïåðåêëþ÷åíèå êîíòåêñòîâ Êàê ïîìåíüøå ïåðåêëþ÷àòü êîíòåêñòû? Ïóñòü íèòè íå îòâëåêàþòñÿ. Îäíè ïèõàþò çàäàíèÿ â î÷åðåäü Äðóãèå âûíèìàþò è èñïîëíÿþò èõ
  178. 178. Öèôðû Ñêîëüêî ðåàëüíî ñòîÿò ðàçëè÷íûå îïåðàöèè? Àòîìàðíûå îïåðàöèè ≈ 0.1ìêñ; incAndGet è volatile 2-3x áûñòðåå CAS Ïåðåêëþ÷åíèå êîíòåêñòà Íåñêîëüêî ìêñ (íåçàâèñèìî îò ÷èñëà íèòåé) Uncontended synchronized ≈ 0.1-1ìêñ Contented synchronized ≈ 20ìêñ http://mailinator.blogspot.com/2008/03/ how-fast-is-java-volatile-or-atomic-or.html ñðàâíåíèå ñêîðîñòè ðàçëè÷íûõ ñïîñîáîâ ñèíõðîíèçàöèè
  179. 179. ×òî óìååò JVM? Biased locking Lock coarsening Lock elision (escape analysis) http: //www.infoq.com/articles/java-threading-optimizations-p1 ho t—v— thre—ding optimiz—tions —™tu—lly workc
  180. 180. ×òî óìååò JVM? Biased locking (new in 1.5.0_6): Áîëüøèíñòâî îáúåêòîâ çà âñþ æèçíü áëîêèðóåò òîëüêî 1 íèòü Äåëàåòñÿ òàê, ÷òîáû äëÿ ýòîé íèòè ñèíõðîíèçàöèÿ áûëà î÷åíü áûñòðîé (äàæå áåç CAS) -XX:+UseBiasedLocking (ïî óìîë÷àíèþ âêëþ÷åíî íà÷èíàÿ ñ Java SE 6) http://tinyurl.com/biasedlocking îò ðàçðàáîò÷èêîâ t†wD ïîEðóññêè
  181. 181. ×òî óìååò JVM? Lock coarsening: public void setupFoo(Foo foo) { foo.setBarCount(1); foo.setQuxEnabled(true); foo.addGazonk(new Gazonk()); } . . . è âñå 3 ìåòîäà synchronized. Òóò íåçà÷åì äåëàòü synchronized 3 ðàçà. Ìîæíî çàïèõíóòü âñå â 1 synchronized. Îïöèÿ -XX:+EliminateLocks (ïî óìîë÷àíèþ âêëþ÷åíî). http://citeseer.ist.psu.edu/459328.html ñòàòüÿ ïðî òåõíèêóF
  182. 182. ×òî óìååò JVM? Escape analysis: Åñëè îáúåêò íå óáåãàåò â äðóãóþ íèòü, òî íåò ñìûñëà äåëàòü íà íåì synchronized. DeepThought dt = new DeepThought(); dt.turnOnPower(); dt.enterData(data); dt.wakeup(); return dt.computeUltimateAnswer(); Îïöèÿ -XX:+DoEscapeAnalysis.
  183. 183. Òåñòèðîâàíèå Òåñòèðîâàòü ìíîãîïîòî÷íûé êîä àäñêè ñëîæíî. Ïðîòåñòèðîâàòü ïðàâèëüíîñòü äåòåðìèíèðîâàííîãî êîäà ìîæíî, õîòü è òðóäíî Ïðîòåñòèðîâàòü îòñóòñòâèå áàãîâ, ñâÿçàííûõ ñ íåäåòåðìèíèçìîì ñîâñåì ñëîæíî Íåò êîíòðîëÿ íàä ãëàâíûì ôàêòîðîì òðóäíîóëîâèìûõ îøèáîê íåäåòåðìèíèçìîì øåäóëåðà Íåîáõîäèìî ñòðåññ-òåñòèðîâàíèå È äàæå îíî íè÷åãî íå ãàðàíòèðóåò Ëó÷øåD êîíå÷íîD äîêàçûâàòü êîððåêòíîñòü Îøèáêè âñå ðàâíî ïðîëåçóò. Èõ äîëæíî áûòü õîðîøî âèäíî.
  184. 184. Òåñòèðîâàíèå ×òî íóæíî îòòåñòèðîâàòü? Êîä ïîñëåäîâàòåëüíî êîððåêòåí Êîä ïðàâèëüíî ðàáîòàåò áåç íàãðóçêè Êîä íå ëîìàåòñÿ ïîä íàãðóçêîé Èìåííî â òàêîì ïîðÿäêå.
  185. 185. Íàëè÷èå îæèäàåìîãî ïîâåäåíèÿ Êàê ïðîâåðèòü, ÷òî ìíîãîïîòî÷íûé êîä ðåàëèçóåò îïðåäåëåííûé ïðîòîêîë â èäåàëüíûõ óñëîâèÿõ? Ïîíàñòàâèòü çàäåðæåê, òåì ñàìûì ñäåëàâ ïîðÿäîê ñîáûòèé äåòåðìèíèðîâàííûì Ïðîâåðèòü, ÷òî ïðîèñõîäÿò íóæíûå ñîáûòèÿ â íóæíîì ïîðÿäêå ÏðîâåðÿòüD ÷òî áëîêèðóþùèå âûçîâû áëîêèðóþòñÿ Èçìåðèòü äëèòåëüíîñòü èëè äîáàâèòü out-ïàðàìåòð didBlock ÏðîâåðÿòüD ÷òî íåáëîêèðóþùèå âûçîâû íå áëîêèðóþòñÿ wo™k o˜je™tsD listeners âî âñåõ âàæíûõ òî÷êàõ êîäà Êðèâî, äëèííî, óðîäëèâî, íî ðàáîòàåò.
  186. 186. Óñòîé÷èâîñòü ê íàãðóçêå Êàê ïðîâåðèòü, ÷òî ìíîãîïîòî÷íûé êîä íå ëîìàåòñÿ ïîä íàãðóçêîé? Ïðèäóìàòü èíâàðèàíòû Îðãàíèçîâàòü íàãðóçêó Ïîñòîÿííî ïðîâåðÿòü èíâàðèàíòû Äëèííî, óðîäëèâî, áåç ãàðàíòèé, íî ðàáîòàåò.
  187. 187. Óñòîé÷èâîñòü ê íàãðóçêå Ïðèìåð: Òåñòèðóåì ConcurrentMap. Èíâàðèàíò: Êàæäûé äîáàâëåííûé, íî íå óäàëåííûé ýëåìåíò ïðèñóòñòâóåò â ìàïå Èíâàðèàíò: size() ðàâíî ÷èñëó äîáàâëåííûõ, íî íå óäàëåííûõ ýëåìåíòîâ.
  188. 188. Óñòîé÷èâîñòü ê íàãðóçêå Ïðèìåð: Òåñòèðóåì ConcurrentMap Ïîâòîðèòü 100000000000000 ðàç Ñãåíåðèðîâàòü IHHHH ñëó÷àéíûõ çíà÷åíèéD ðàçáèòü íà IH ÷àñòåé ñëó÷àéíûì îáðàçîì  IH íèòåéX äîáàâëÿòü â ìàïó çíà÷åíèÿ èç i-é ÷àñòè ñî ñëó÷àéíûìè íåáîëüøèìè çàäåðæêàìè ïðîâåðÿòü, ÷òî âñå ïðåäûäóùèå çíà÷åíèÿ èç i-é ÷àñòè â ìàïå åñòü Ïî îêîí÷àíèè ïðîâåðèòü íàëè÷èå êàæäîãî çíà÷åíèÿ Ïðèãîäèòñÿ CyclicBarrier
  189. 189. Ïîâòîðÿåìîñòü Êàê ïîâòîðèòü ãîòîâóþ îøèáêó? Íàïèñàòü äåëåãèðóþùèå mock-îáúåêòû, çàïèñûâàþùèå âñå äåéñòâèÿ Äîæäàòüñÿ îøèáêè Íàïèñàòü mock-îáúåêòû, ïðîèãðûâàþùèå çàäàííûé ñöåíàðèé Ïîìîæåò íàéòè ãîíêè â ïðîòîêîëå. Íå ïîìîæåò íàéòè íèçêîóðîâíåâûå ãîíêè (ìåæäó statement'àìè). Áåç ìîçãîâ íå îáîéòèñü!
  190. 190. Êàê ñïðîâîöèðîâàòü îøèáêó Êàê îðãàíèçîâàòü ìàêñèìóì íåäåòåðìèíèçìà øåäóëåðà? Ïîíàñòàâèòü Thread.yield() èëè Thread.sleep(1) â ðàçíûõ ìåñòàõ êîäà Èñïîëüçîâàòü ≈ 2 ∗ NCPU íèòåé ×òîáû è âñå g€… áûëè çàíÿòûD à íèòè è âûòåñíÿëèñüD è íå ïðîñòàèâàëè ñëèøêîì äîëãî
  191. 191. ×òî äåëàòü ñ ïðîèçîøåäøèìè îøèáêàìè Ãëàâíîå íå äàòü èì óñêîëüçíóòü. Íå äàâàòü ” îãíåîïàñíûå“ âû÷èñëåíèÿ âíåøíèì API îíè ÷àñòî ãëîòàþò èñêëþ÷åíèÿ. Îáåðòûâàòü ëîããèíãîì. ixe™utorƒervi™e Îáðàáîò÷èêè ñîáûòèé â q‡„ ÏîëàãàþD îíè íå îäèíîêèF Ïî âîçìîæíîñòè íå òåðÿòü èíôîðìàöèþ î ïîòîêå èñïîëíåíèÿ
  192. 192. ×òî äåëàòü ñ ïðîèçîøåäøèìè îøèáêàìè Ãëàâíîå íå äàòü èì óñêîëüçíóòü. Íå äàâàòü ” îãíåîïàñíûå“ âû÷èñëåíèÿ âíåøíèì API îíè ÷àñòî ãëîòàþò èñêëþ÷åíèÿ. Îáåðòûâàòü ëîããèíãîì. Ïî âîçìîæíîñòè íå òåðÿòü èíôîðìàöèþ î ïîòîêå èñïîëíåíèÿ Ïðè àñèíõðîííîì âûçîâå çàïîìíèòü ñòåêòðåéñ èíèöèàòîðàX îí ïðèãîäèòñÿ ïðè èñêëþ÷åíèè â ðåàêòîðåF Àðòèëëåðèÿ äëÿ îòëàäêè äåäëîêîâX áëîêèðóåìûé ðåñóðñ õðàíèò ñòåêòðåéñ çàõâàòàF Ïðîâåðåíî â áîåâûõ óñëîâèÿõ. Áåçóìíûå èçäåðæêè, íî ðåäêèé áàã óñòîèò.
  193. 193. Òóëû TestNG èìååò íåáîëüøèå ñïåöèàëüíûå ñðåäñòâà @Test(threadPoolSize=5,invocationCount=10,threadMap=2,2,2,3,1) MultithreadedTC (http://code.google.com/p/multithreadedtc/A assertTick(n), waitForTick(n) Ïîíàñòàâèòü òèêîâ ìîæíî òîëüêî â òåñòîâîì êîäå Óïîìÿíóòûé tEvyD tr—™e™he™k F F F
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×