From 6994bb7a3471e3b0bbbad14f3d25ada5e5e92f1a Mon Sep 17 00:00:00 2001 From: ridethepig Date: Tue, 11 Apr 2023 20:48:42 +0800 Subject: [PATCH] OSTEP chatper 30 --- assets/ostep_1681115599584_0.edn | 641 +++++++++++++++++++++++++++- pages/hls__ostep_1681115599584_0.md | 204 ++++++++- 2 files changed, 834 insertions(+), 11 deletions(-) diff --git a/assets/ostep_1681115599584_0.edn b/assets/ostep_1681115599584_0.edn index a334635..0ac733e 100644 --- a/assets/ostep_1681115599584_0.edn +++ b/assets/ostep_1681115599584_0.edn @@ -1173,5 +1173,644 @@ :height 1382.4}), :page 358}, :content {:text " the lock is not acquired during the first spin phase, a second phase is entered, where the caller is put to sleep, and only woken up when the lock becomes free later."}, + :properties {:color "yellow"}} + {:id #uuid "643525b0-e245-489b-877d-a2a1d63e7ea6", + :page 361, + :position {:bounding {:x1 174.14286422729492, + :y1 325.0178756713867, + :x2 645.9385185241699, + :y2 360.44644927978516, + :width 806.3999999999999, + :height 1209.6}, + :rects ({:x1 174.14286422729492, + :y1 325.0178756713867, + :x2 645.9385185241699, + :y2 360.44644927978516, + :width 806.3999999999999, + :height 1209.6}), + :page 361}, + :content {:text "Lock-based Concurrent Data Structures"}, + :properties {:color "yellow"}} + {:id #uuid "643525e5-fb85-48d4-905a-2a88b9ac0b0d", + :page 361, + :position {:bounding {:x1 108.35714340209961, + :y1 815.107177734375, + :x2 298.91018295288086, + :y2 835.6786193847656, + :width 806.3999999999999, + :height 1209.6}, + :rects ({:x1 108.35714340209961, + :y1 815.107177734375, + :x2 298.91018295288086, + :y2 835.6786193847656, + :width 806.3999999999999, + :height 1209.6}), + :page 361}, + :content {:text "Concurrent Counters"}, + :properties {:color "yellow"}} + {:id #uuid "64352751-d9bd-4d5e-a8ba-cd18f86b1a15", + :page 363, + :position {:bounding {:x1 156.65179443359375, + :y1 746.232177734375, + :x2 260.2728805541992, + :y2 762.8036193847656, + :width 806.3999999999999, + :height 1209.6}, + :rects ({:x1 156.65179443359375, + :y1 746.232177734375, + :x2 260.2728805541992, + :y2 762.8036193847656, + :width 806.3999999999999, + :height 1209.6}), + :page 363}, + :content {:text "perfect scaling"}, + :properties {:color "yellow"}} + {:id #uuid "64352794-d7c8-42f9-8321-f874967cebf2", + :page 363, + :position {:bounding {:x1 376.82144927978516, + :y1 967.5000305175781, + :x2 523.3794326782227, + :y2 984.0715026855469, + :width 806.3999999999999, + :height 1209.6}, + :rects ({:x1 376.82144927978516, + :y1 967.5000305175781, + :x2 523.3794326782227, + :y2 984.0715026855469, + :width 806.3999999999999, + :height 1209.6}), + :page 363}, + :content {:text "approximate counter"}, + :properties {:color "yellow"}} + {:id #uuid "643530d8-9d09-4c8a-9e92-47dfe814ef50", + :page 367, + :position {:bounding {:x1 116.09400177001953, + :y1 446.52679443359375, + :x2 350.7183532714844, + :y2 468.24107360839844, + :width 864, + :height 1296}, + :rects ({:x1 116.09400177001953, + :y1 446.52679443359375, + :x2 350.7183532714844, + :y2 468.24107360839844, + :width 864, + :height 1296}), + :page 367}, + :content {:text "Concurrent Linked Lists"}, + :properties {:color "yellow"}} + {:id #uuid "64353237-4b74-4148-b7c1-5854d83a18c7", + :page 369, + :position {:bounding {:x1 255.12501525878906, + :y1 1018.0357666015625, + :x2 451.5310516357422, + :y2 1035.7500610351562, + :width 864, + :height 1296}, + :rects ({:x1 255.12501525878906, + :y1 1018.0357666015625, + :x2 451.5310516357422, + :y2 1035.7500610351562, + :width 864, + :height 1296}), + :page 369}, + :content {:text "hand-over-hand locking"}, + :properties {:color "yellow"}} + {:id #uuid "64353353-9de2-421b-967d-dc80a597eecd", + :page 370, + :position {:bounding {:x1 171.89286422729492, + :y1 644.6607360839844, + :x2 361.0623435974121, + :y2 666.3750305175781, + :width 864, + :height 1296}, + :rects ({:x1 171.89286422729492, + :y1 644.6607360839844, + :x2 361.0623435974121, + :y2 666.3750305175781, + :width 864, + :height 1296}), + :page 370}, + :content {:text "Concurrent Queues"}, + :properties {:color "yellow"}} + {:id #uuid "6435360d-c176-494a-9d61-b1fd0107a9bd", + :page 372, + :position {:bounding {:x1 171.89286041259766, + :y1 604.0268096923828, + :x2 395.03311920166016, + :y2 625.7411041259766, + :width 864, + :height 1296}, + :rects ({:x1 171.89286041259766, + :y1 604.0268096923828, + :x2 395.03311920166016, + :y2 625.7411041259766, + :width 864, + :height 1296}), + :page 372}, + :content {:text "Concurrent Hash Table"}, + :properties {:color "yellow"}} + {:id #uuid "6435363d-c697-42a6-bfd0-8a2332cef394", + :page 372, + :position {:bounding {:x1 0, + :y1 445.1428680419922, + :x2 745.5475311279297, + :y2 804.1607513427734, + :width 864, + :height 1296}, + :rects ({:x1 0, + :y1 445.1428680419922, + :x2 0, + :y2 466.28575134277344, + :width 864, + :height 1296} + {:x1 532.4713592529297, + :y1 766.5178680419922, + :x2 745.5475311279297, + :y2 784.2321624755859, + :width 864, + :height 1296} + {:x1 171.89286041259766, + :y1 786.4464569091797, + :x2 632.3166275024414, + :y2 804.1607513427734, + :width 864, + :height 1296}), + :page 372}, + :content {:text "instead of having a single lock for the entire structure, it uses a lock per hash bucket"}, + :properties {:color "yellow"}} + {:id #uuid "6435365a-b5d6-46fc-a9a1-25b0d23aa529", + :page 372, + :position {:bounding {:x1 564.7891998291016, + :y1 1059.107177734375, + :x2 651.2378387451172, + :y2 1076.8214721679688, + :width 864, + :height 1296}, + :rects ({:x1 564.7891998291016, + :y1 1059.107177734375, + :x2 651.2378387451172, + :y2 1076.8214721679688, + :width 864, + :height 1296}), + :page 372}, + :content {:text "ubiquitous "}, + :properties {:color "green"}} + {:id #uuid "6435367f-dd9e-449d-b0e4-3d8c9e14f6c2", + :page 373, + :position {:bounding {:x1 320.9654083251953, + :y1 875.2946624755859, + :x2 378.3458709716797, + :y2 893.0089569091797, + :width 864, + :height 1296}, + :rects ({:x1 320.9654083251953, + :y1 875.2946624755859, + :x2 378.3458709716797, + :y2 893.0089569091797, + :width 864, + :height 1296}), + :page 373}, + :content {:text "humble "}, + :properties {:color "green"}} + {:id #uuid "643536c8-fc05-4bbe-8d1d-0f4f6d1c4fee", + :page 376, + :position {:bounding {:x1 443.3345642089844, + :y1 585.2410888671875, + :x2 497.6003112792969, + :y2 602.9553833007812, + :width 864, + :height 1296}, + :rects ({:x1 443.3345642089844, + :y1 585.2410888671875, + :x2 497.6003112792969, + :y2 602.9553833007812, + :width 864, + :height 1296}), + :page 376}, + :content {:text "sloppy "}, + :properties {:color "green"}} + {:id #uuid "643537d3-7d01-442b-b47e-59433c2aa6db", + :page 378, + :position {:bounding {:x1 596.2246246337891, + :y1 701.2500305175781, + :x2 659.0949554443359, + :y2 718.9643249511719, + :width 864, + :height 1296}, + :rects ({:x1 596.2246246337891, + :y1 701.2500305175781, + :x2 659.0949554443359, + :y2 718.9643249511719, + :width 864, + :height 1296}), + :page 378}, + :content {:text "grossly "}, + :properties {:color "green"}} + {:id #uuid "643537ff-1028-4725-8d7a-c0338cc946d3", + :page 378, + :position {:bounding {:x1 293.5893096923828, + :y1 858.1875305175781, + :x2 445.99464416503906, + :y2 881.6160888671875, + :width 864, + :height 1296}, + :rects ({:x1 293.5893096923828, + :y1 858.1875305175781, + :x2 445.99464416503906, + :y2 881.6160888671875, + :width 864, + :height 1296}), + :page 378}, + :content {:text "condition variable"}, + :properties {:color "yellow"}} + {:id #uuid "64353882-7697-4c16-8e53-c8f59ea256c1", + :page 378, + :position {:bounding {:x1 0, + :y1 477.1428642272949, + :x2 747.7302322387695, + :y2 981.2410888671875, + :width 864, + :height 1296}, + :rects ({:x1 0, + :y1 477.1428642272949, + :x2 0, + :y2 498.28572273254395, + :width 864, + :height 1296} + {:x1 0, + :y1 493.1428656578064, + :x2 0, + :y2 514.2857241630554, + :width 864, + :height 1296} + {:x1 0, + :y1 509.14286613464355, + :x2 0, + :y2 530.2857246398926, + :width 864, + :height 1296} + {:x1 0, + :y1 525.1428661346436, + :x2 0, + :y2 546.2857246398926, + :width 864, + :height 1296} + {:x1 0, + :y1 541.1428680419922, + :x2 0, + :y2 562.2857246398926, + :width 864, + :height 1296} + {:x1 484.25003814697266, + :y1 858.1875305175781, + :x2 641.9464797973633, + :y2 881.6160888671875, + :width 864, + :height 1296} + {:x1 463.3002700805664, + :y1 859.8482360839844, + :x2 747.3339920043945, + :y2 877.7767944335938, + :width 864, + :height 1296} + {:x1 171.8928680419922, + :y1 879.7768249511719, + :x2 745.5433197021484, + :y2 897.7053833007812, + :width 864, + :height 1296} + {:x1 262.47322845458984, + :y1 898.0357360839844, + :x2 341.1931381225586, + :y2 921.4643249511719, + :width 864, + :height 1296} + {:x1 531.553596496582, + :y1 898.0357360839844, + :x2 601.7216262817383, + :y2 921.4643249511719, + :width 864, + :height 1296} + {:x1 171.8928680419922, + :y1 899.6964416503906, + :x2 747.192024230957, + :y2 917.6250305175781, + :width 864, + :height 1296} + {:x1 171.8928680419922, + :y1 919.6250305175781, + :x2 745.5449066162109, + :y2 937.5535888671875, + :width 864, + :height 1296} + {:x1 717.848274230957, + :y1 937.8928833007812, + :x2 747.7302322387695, + :y2 961.3214721679688, + :width 864, + :height 1296} + {:x1 171.8928680419922, + :y1 939.5535888671875, + :x2 747.7302322387695, + :y2 957.482177734375, + :width 864, + :height 1296} + {:x1 171.8928680419922, + :y1 957.8125305175781, + :x2 229.24837493896484, + :y2 981.2410888671875, + :width 864, + :height 1296} + {:x1 171.8928680419922, + :y1 960.669677734375, + :x2 371.48160552978516, + :y2 978.5982360839844, + :width 864, + :height 1296}), + :page 378}, + :content {:text "A condition variable is an explicit queue that threads can put themselves on when some state of execution(i.e., some condition) is not as desired (by waiting on the condition); some other thread, when it changes said state, can then wake one (or more) of those waiting threads and thus allow them to continue (by signaling on the condition). "}, + :properties {:color "yellow"}} + {:id #uuid "643538d5-9ea3-4399-9fa2-d75fdf0e1dd4", + :page 378, + :position {:bounding {:x1 0, + :y1 653.1428680419922, + :x2 747.631721496582, + :y2 1116.6607666015625, + :width 864, + :height 1296}, + :rects ({:x1 0, + :y1 653.1428680419922, + :x2 0, + :y2 674.2857284545898, + :width 864, + :height 1296} + {:x1 650.6428909301758, + :y1 1079.0178833007812, + :x2 747.631721496582, + :y2 1096.9464721679688, + :width 864, + :height 1296} + {:x1 171.8928680419922, + :y1 1098.9464721679688, + :x2 594.3628997802734, + :y2 1116.6607666015625, + :width 864, + :height 1296}), + :page 378}, + :content {:text "wait() call is executed when a thread wishes to put itself to sleep;"}, + :properties {:color "yellow"}} + {:id #uuid "643538de-cc40-4dd2-8f03-9492004f209b", + :page 379, + :position {:bounding {:x1 0, + :y1 541.1428680419922, + :x2 689.7592334747314, + :y2 885.2500305175781, + :width 864, + :height 1296}, + :rects ({:x1 0, + :y1 541.1428680419922, + :x2 0, + :y2 562.2857360839844, + :width 864, + :height 1296} + {:x1 116.09822273254395, + :y1 847.607177734375, + :x2 689.7592334747314, + :y2 865.3214721679688, + :width 864, + :height 1296} + {:x1 116.09822273254395, + :y1 867.5357360839844, + :x2 633.988603591919, + :y2 885.2500305175781, + :width 864, + :height 1296}), + :page 379}, + :content {:text "is executed when a thread has changed something in the program and thus wants to wake a sleeping thread waiting on this condition. S"}, + :properties {:color "yellow"}} + {:id #uuid "64353eb8-8ed8-4680-a3c0-91608b429408", + :page 379, + :position {:bounding {:x1 360.32312774658203, + :y1 1098.9464721679688, + :x2 409.81058502197266, + :y2 1116.6607666015625, + :width 864, + :height 1296}, + :rects ({:x1 360.32312774658203, + :y1 1098.9464721679688, + :x2 409.81058502197266, + :y2 1116.6607666015625, + :width 864, + :height 1296}), + :page 379}, + :content {:text "stems "}, + :properties {:color "green"}} + {:id #uuid "643547c5-1613-49e9-899e-0e86f59a1462", + :page 380, + :position {:bounding {:x1 0, + :y1 285.14288330078125, + :x2 747.3582305908203, + :y2 563.0268249511719, + :width 864, + :height 1296}, + :rects ({:x1 0, + :y1 285.14288330078125, + :x2 0, + :y2 306.2857437133789, + :width 864, + :height 1296} + {:x1 541.1089324951172, + :y1 525.1786041259766, + :x2 747.3582305908203, + :y2 543.107177734375, + :width 864, + :height 1296} + {:x1 171.89286422729492, + :y1 545.0982513427734, + :x2 745.9600219726562, + :y2 563.0268249511719, + :width 864, + :height 1296}), + :page 380}, + :content {:text "uses a while loop instead of just an if statement when deciding whether to wait on the condition."}, + :properties {:color "yellow"}} + {:id #uuid "64354974-adea-4b20-90f4-a12ebe1e4d5b", + :page 382, + :position {:bounding {:x1 279.43043518066406, + :y1 543.8750152587891, + :x2 506.8169403076172, + :y2 567.3035888671875, + :width 864, + :height 1296}, + :rects ({:x1 279.4464416503906, + :y1 543.8750152587891, + :x2 443.5089569091797, + :y2 567.3035888671875, + :width 864, + :height 1296} + {:x1 279.43043518066406, + :y1 545.5357208251953, + :x2 506.8169403076172, + :y2 563.4642944335938, + :width 864, + :height 1296}), + :page 382}, + :content {:text "producer/consumer problem,"}, + :properties {:color "yellow"}} + {:id #uuid "64354cc4-14c5-408d-b879-7d4d011b2b5c", + :page 385, + :position {:bounding {:x1 294.6515197753906, + :y1 1077.3572082519531, + :x2 425.10882568359375, + :y2 1100.7857971191406, + :width 864, + :height 1296}, + :rects ({:x1 294.6785888671875, + :y1 1077.3572082519531, + :x2 425.10882568359375, + :y2 1100.7857971191406, + :width 864, + :height 1296} + {:x1 294.6515197753906, + :y1 1079.0179138183594, + :x2 294.65740966796875, + :y2 1096.7322082519531, + :width 864, + :height 1296}), + :page 385}, + :content {:text "Mesa semantics"}, + :properties {:color "yellow"}} + {:id #uuid "64354d46-4286-44fd-9e82-2ba562a50f25", + :page 386, + :position {:bounding {:x1 0, + :y1 477.1428909301758, + :x2 746.0656509399414, + :y2 818.6518249511719, + :width 864, + :height 1296}, + :rects ({:x1 0, + :y1 477.1428909301758, + :x2 0, + :y2 498.28575134277344, + :width 864, + :height 1296} + {:x1 171.89286422729492, + :y1 779.3482666015625, + :x2 308.99941635131836, + :y2 802.7768249511719, + :width 864, + :height 1296} + {:x1 308.9821548461914, + :y1 781.0089721679688, + :x2 746.0656509399414, + :y2 798.9375610351562, + :width 864, + :height 1296} + {:x1 171.89286422729492, + :y1 800.9375610351562, + :x2 693.3923149108887, + :y2 818.6518249511719, + :width 864, + :height 1296}), + :page 386}, + :content {:text "Hoare semantics, is harder to build but provides a stronger guarantee that the woken thread will run immediately upon being woken "}, + :properties {:color "yellow"}} + {:id #uuid "64354db0-8c74-4c14-b063-d26378a10555", + :page 386, + :position {:bounding {:x1 281.8214340209961, + :y1 997.6697082519531, + :x2 477.6873245239258, + :y2 1021.0982971191406, + :width 864, + :height 1296}, + :rects ({:x1 286.6964340209961, + :y1 997.6697082519531, + :x2 477.6873245239258, + :y2 1021.0982971191406, + :width 864, + :height 1296} + {:x1 281.8214340209961, + :y1 999.3304138183594, + :x2 477.6873245239258, + :y2 1017.2590026855469, + :width 864, + :height 1296}), + :page 386}, + :content {:text " always use while loops"}, + :properties {:color "yellow"}} + {:id #uuid "64354f54-b26c-48dc-a328-4ae355b680f3", + :page 390, + :position {:bounding {:x1 593.6900482177734, + :y1 484.1875305175781, + :x2 652.7586212158203, + :y2 501.9018249511719, + :width 864, + :height 1296}, + :rects ({:x1 593.6900482177734, + :y1 484.1875305175781, + :x2 652.7586212158203, + :y2 501.9018249511719, + :width 864, + :height 1296}), + :page 390}, + :content {:text "albeit "}, + :properties {:color "green"}} + {:id #uuid "64355441-5a1b-4015-baa1-65917526079c", + :page 391, + :position {:bounding {:x1 494.5921096801758, + :y1 1057.4464721679688, + :x2 649.2800369262695, + :y2 1080.8750610351562, + :width 864, + :height 1296}, + :rects ({:x1 494.61609649658203, + :y1 1057.4464721679688, + :x2 649.2800369262695, + :y2 1080.8750610351562, + :width 864, + :height 1296} + {:x1 494.5921096801758, + :y1 1059.1072082519531, + :x2 649.2800369262695, + :y2 1076.8214721679688, + :width 864, + :height 1296}), + :page 391}, + :content {:text "covering condition"}, + :properties {:color "yellow"}} + {:id #uuid "643554f4-75a7-48fa-9366-87058ee723fb", + :page 390, + :position {:bounding {:x1 171.89286422729492, + :y1 317.60716247558594, + :x2 249.12459182739258, + :y2 341.0357208251953, + :width 864, + :height 1296}, + :rects ({:x1 171.89286422729492, + :y1 317.60716247558594, + :x2 249.12459182739258, + :y2 341.0357208251953, + :width 864, + :height 1296}), + :page 390}, + :content {:text "spurious "}, + :properties {:color "green"}} + {:id #uuid "64355502-f41f-40dd-b71f-e0abdbc76716", + :page 390, + :position {:bounding {:x1 171.89286422729492, + :y1 317.60716247558594, + :x2 322.3585624694824, + :y2 341.0357208251953, + :width 864, + :height 1296}, + :rects ({:x1 171.89286422729492, + :y1 317.60716247558594, + :x2 322.3585624694824, + :y2 341.0357208251953, + :width 864, + :height 1296}), + :page 390}, + :content {:text "spurious wakeups"}, :properties {:color "yellow"}}], - :extra {:page 361}} + :extra {:page 396}} diff --git a/pages/hls__ostep_1681115599584_0.md b/pages/hls__ostep_1681115599584_0.md index f2f97bf..523653b 100644 --- a/pages/hls__ostep_1681115599584_0.md +++ b/pages/hls__ostep_1681115599584_0.md @@ -370,7 +370,7 @@ file-path:: ../assets/ostep_1681115599584_0.pdf hl-page:: 357 hl-color:: yellow id:: 64352221-d590-4371-a5f0-29e9cfa75ccb -- efficacy +- efficacy 功效,效力 ls-type:: annotation hl-page:: 341 hl-color:: green @@ -380,23 +380,207 @@ file-path:: ../assets/ostep_1681115599584_0.pdf hl-page:: 347 hl-color:: green id:: 6434f523-44b7-40ab-8fea-528969c5acfd -- delve +- delve 钻研;探究;挖 ls-type:: annotation hl-page:: 349 hl-color:: green id:: 6434fb8c-2b3b-4d80-83fb-3b34da4dcd28 -- brag +- brag 吹嘘;自吹自擂 ls-type:: annotation hl-page:: 351 hl-color:: green id:: 643501c1-f11b-4e85-8125-d2a5a31f69b0 -- intergalactic - ls-type:: annotation - hl-page:: 355 - hl-color:: green - id:: 643509b5-12a0-4ed9-8a96-f70b3fc0e373 - scourge +- 鞭打;鞭笞;折磨;使受苦难 +- Lock-based Concurrent Data Structures ls-type:: annotation - hl-page:: 355 + hl-page:: 361 + hl-color:: yellow + id:: 643525b0-e245-489b-877d-a2a1d63e7ea6 + - **Concurrent Counters** + hl-page:: 361 + ls-type:: annotation + id:: 643525e5-fb85-48d4-905a-2a88b9ac0b0d + hl-color:: yellow + collapsed:: true + - **Counter with lock** + - Wrap the all the operations with a single lock. + - Performance is bad due to lock contention and it gets worse when the number of threads increases. + - **perfect scaling**: the increase in thread number doesn't harm the performance + hl-page:: 363 + ls-type:: annotation + id:: 64352751-d9bd-4d5e-a8ba-cd18f86b1a15 + hl-color:: yellow + - **approximate counter** + hl-page:: 363 + ls-type:: annotation + id:: 64352794-d7c8-42f9-8321-f874967cebf2 + hl-color:: yellow + - represent a single logical counter via ==numerous local physical counters==(one per CPU core), as well as ==a single global counter==. Each actual counter has a ==lock==. + - To add the counter, acquire the ==local lock== and increase it, thus avoiding contention. + - To read the counter, acquire the ==global lock== and read. + - To keep the global counter up to date, the local values are periodically transferred to the global counter and reset, which requires ==global lock and local lock==. A threshold `S` determines how often this transfer happens, tuning the trade-off between scalability and precision. + - **Concurrent Linked Lists** + ls-type:: annotation + hl-page:: 367 + hl-color:: yellow + id:: 643530d8-9d09-4c8a-9e92-47dfe814ef50 + collapsed:: true + - Again, the simplest way to implement this is to wrap all operations on the list with a single lock. + - Assuming the `malloc` is ==thread-safe==, we can improve the code a little by narrowing critical section: only operations on global structure need to be locked. + - **hand-over-hand locking**: a lock per node. + hl-page:: 369 + ls-type:: annotation + id:: 64353237-4b74-4148-b7c1-5854d83a18c7 + hl-color:: yellow + - When traversing the list, the code first grabs the next node's lock and then releases the current node's lock. + - In practice, it ==doesn't work== due to prohibitive overhead + - **Concurrent Queues** + ls-type:: annotation + hl-page:: 370 + hl-color:: yellow + id:: 64353353-9de2-421b-967d-dc80a597eecd + - Two locks, head and tail, for `enqueue` and `dequeue` operation. + - Add a dummy node to separate head and tail operation. Without this, `dequeue` operation needs to acquire both locks in case the queue is empty. + - **Concurrent Hash Table** + hl-page:: 372 + ls-type:: annotation + id:: 6435360d-c176-494a-9d61-b1fd0107a9bd + hl-color:: yellow + - instead of having a single lock for the entire structure, it uses a lock per hash bucket + ls-type:: annotation + hl-page:: 372 + hl-color:: yellow + id:: 6435363d-c697-42a6-bfd0-8a2332cef394 +- ubiquitous 似乎无所不在的;十分普遍的 + ls-type:: annotation + hl-page:: 372 hl-color:: green - id:: 643509ba-662e-4d0a-906a-fd0987e24574 \ No newline at end of file + id:: 6435365a-b5d6-46fc-a9a1-25b0d23aa529 +- humble 谦逊;低声下气;虚心;贬低 + ls-type:: annotation + hl-page:: 373 + hl-color:: green + id:: 6435367f-dd9e-449d-b0e4-3d8c9e14f6c2 +- sloppy 马虎的,草率的;(衣服)宽松肥大的;太稀的,不够稠的; + hl-page:: 376 + ls-type:: annotation + id:: 643536c8-fc05-4bbe-8d1d-0f4f6d1c4fee + hl-color:: green +- gross 总的,毛的;严重的,极端的;粗鲁的;臃肿的;粗略的; + hl-page:: 378 + ls-type:: annotation + id:: 643537d3-7d01-442b-b47e-59433c2aa6db + hl-color:: green +- **condition variable** + hl-page:: 378 + ls-type:: annotation + id:: 643537ff-1028-4725-8d7a-c0338cc946d3 + hl-color:: yellow + - A ==condition variable== is an explicit queue that threads can put themselves on when some state of execution(condition) is not as desired (by *waiting on the condition*); some other thread, when it changes said state, can then wake one (or more) of those waiting threads and thus allow them to continue (by *signaling*). + hl-page:: 378 + ls-type:: annotation + id:: 64353882-7697-4c16-8e53-c8f59ea256c1 + hl-color:: yellow + - Operations + - `wait()` put the caller to sleep. `pthread_cond_wait(pthread_cond_t *c, pthread_mutex_t *m)` + hl-page:: 378 + ls-type:: annotation + id:: 643538d5-9ea3-4399-9fa2-d75fdf0e1dd4 + hl-color:: yellow + - `signal()` wake up a sleeping thread waiting on this condition. `pthread_cond_signal(pthread_cond_t *c);` + hl-page:: 379 + ls-type:: annotation + id:: 643538de-cc40-4dd2-8f03-9492004f209b + hl-color:: yellow + - The `wait()` also takes a mutex as a parameter; it assumes that this mutex is locked when `wait()` is called. The responsibility of `wait()` is to ==release the lock and put the calling thread to sleep== (atomically); when the thread wakes up, it must ==re-acquire the lock before returning== to the caller. The design is helpful to avoid some race conditions when trying to sleep. + - use a while loop instead of just an if statement when deciding whether to wait on the condition. + ls-type:: annotation + hl-page:: 380 + hl-color:: yellow + id:: 643547c5-1613-49e9-899e-0e86f59a1462 +- stem + ls-type:: annotation + hl-page:: 379 + hl-color:: green + id:: 64353eb8-8ed8-4680-a3c0-91608b429408 +- **producer/consumer problem** + hl-page:: 382 + ls-type:: annotation + id:: 64354974-adea-4b20-90f4-a12ebe1e4d5b + hl-color:: yellow + - **Mesa semantics**: Signaling a thread only wakes them up; it is thus a hint that the state of the world has ==changed==, but there is ==no guarantee== that when the woken thread runs, the state will ==still be as desired==. (Another guy may run before the thread and change the state again) + hl-page:: 385 + ls-type:: annotation + id:: 64354cc4-14c5-408d-b879-7d4d011b2b5c + hl-color:: yellow + - So, always use while loops. While loops make sure the thread wake up in the desired state of world, which tackles the ((64355502-f41f-40dd-b71f-e0abdbc76716)) and provides support for ((64355441-5a1b-4015-baa1-65917526079c)) + hl-page:: 386 + ls-type:: annotation + id:: 64354db0-8c74-4c14-b063-d26378a10555 + hl-color:: yellow + - **Hoare semantics**: provides a stronger guarantee that the woken thread will run immediately upon being woken + hl-page:: 386 + ls-type:: annotation + id:: 64354d46-4286-44fd-9e82-2ba562a50f25 + hl-color:: yellow + - Incorrect Solution: single condition variable. The problem arises from the ==undirected wakeup operation==: God knows which thread is to be woken up. + - Envision multiple consumers and one producer: + 1. producer `P1` increases count to 1, signals the CV and sleeps + 2. consumer `C1` is awaken, reduces count to 0, signals the CV and sleeps + 3. another consumer `C2` is woken up ==by accident==, finds out count is 0, sleeps + 4. In this case, they all sleep and thus nobody will signal any of them + - If in step 3, the producer `P1` is woken up, everything is fine. Obviously, one solution is to ==exert control over which thread is to be woken up==. Well, wake up all threads may also solve this problem, see ((64355441-5a1b-4015-baa1-65917526079c)). + - Correct solution: 2 condition variable. + - Producer threads wait on the condition `empty`, and signals `fill`. Conversely, consumer threads wait on `fill` and signal `empty`. + - Code + ```C + cond_t empty, fill; + mutex_t mutex; + void *producer(void *arg) { + int i; + for (i = 0; i < loops; i++) { + Pthread_mutex_lock(&mutex); + while (count == MAX) + Pthread_cond_wait(&empty, &mutex); + put(i); + Pthread_cond_signal(&fill); + Pthread_mutex_unlock(&mutex); + } + } + void *consumer(void *arg) { + int i; + for (i = 0; i < loops; i++) { + Pthread_mutex_lock(&mutex); + while (count == 0) + Pthread_cond_wait(&fill, &mutex); + int tmp = get(); + Pthread_cond_signal(&empty); + Pthread_mutex_unlock(&mutex); + printf("%d\n", tmp); + } + } + ``` + - **spurious wakeups** + hl-page:: 390 + ls-type:: annotation + id:: 64355502-f41f-40dd-b71f-e0abdbc76716 + hl-color:: yellow + - In some thread packages, due to details of the implementation, it is possible that two threads get woken up though just a single signal has taken place. + - **covering condition** + hl-page:: 391 + ls-type:: annotation + id:: 64355441-5a1b-4015-baa1-65917526079c + hl-color:: yellow + - covers all the cases where a thread needs to wake up, those unneeded simply wake up, re-check condition and go back to sleep + - `pthread_cond_broadcast()` wakes up all waiting threads +- albeit 尽管;虽然 + ls-type:: annotation + hl-page:: 390 + hl-color:: green + id:: 64354f54-b26c-48dc-a328-4ae355b680f3 +- spurious 虚假的;伪造的;建立在错误的观念(或思想方法)之上的;谬误的 + hl-page:: 390 + ls-type:: annotation + id:: 643554f4-75a7-48fa-9366-87058ee723fb + hl-color:: green \ No newline at end of file