[{"data":1,"prerenderedAt":4559},["ShallowReactive",2],{"wiki-page-\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1900-1700-semaphore-latch-barrier":3,"wiki-doc-items-2023-10-05-cplusplus-jiao-xue":3999,"wiki:author-members":4547},{"id":4,"title":5,"authors":6,"body":8,"chapterDepth":43,"chapterOrder":3987,"date":3988,"description":14,"docKey":3989,"docRoot":3990,"docTitle":3991,"extension":3992,"isWikiDoc":358,"isWikiIndex":3993,"meta":3994,"navigation":358,"path":3995,"seo":3996,"stem":3997,"wikiDepth":29,"__hash__":3998},"wiki\u002Fwiki\u002F2023-10-05-Cplusplus教学\u002F2000-1900-1700-semaphore-latch-barrier.md","semaphore、latch 与 barrier",[7],"董佳辉",{"type":9,"value":10,"toc":3931},"minimark",[11,15,61,64,100,107,110,118,121,127,130,136,139,142,145,150,155,161,166,169,178,181,187,190,196,199,215,218,224,227,233,235,241,243,249,252,266,269,276,279,285,288,291,297,299,303,305,310,705,708,714,717,723,726,753,756,759,765,768,795,798,801,807,809,813,818,825,828,847,850,857,859,865,868,874,877,883,886,892,895,900,903,905,908,910,939,942,948,951,957,960,967,969,975,978,985,988,1017,1020,1023,1035,1038,1050,1053,1059,1062,1064,1070,1073,1079,1082,1127,1130,1136,1139,1154,1157,1159,1163,1166,1181,1184,1198,1200,1206,1208,1214,1217,1223,1226,1228,1234,1237,1248,1251,1258,1261,1267,1269,1293,1296,1302,1304,1318,1321,1324,1337,1340,1346,1348,1352,1354,1374,1377,1383,1386,1398,1401,1407,1410,1422,1424,1430,1433,1439,1441,1445,1448,1460,1463,1468,1474,1479,1485,1488,1494,1497,1503,1506,1508,1512,1514,1531,1534,1549,1552,1555,1583,1586,1598,1601,1604,1610,1613,1619,1622,1628,1631,1633,1637,1639,1673,1676,1682,1685,1696,1699,1705,1708,1711,1717,1720,1726,1729,1735,1738,1741,1747,1749,1753,1757,1763,1770,1772,1794,1796,1802,1805,1820,1823,1826,1832,1835,1841,1844,1846,1850,1853,1860,1862,1868,1870,1874,2123,2125,2131,2134,2136,2142,2145,2151,2154,2157,2163,2166,2172,2174,2179,2191,2193,2200,2202,2208,2211,2216,2219,2221,2226,2239,2241,2248,2251,2257,2260,2263,2269,2271,2277,2280,2286,2289,2291,2297,2300,2306,2309,2323,2325,2331,2334,2355,2361,2363,2367,2370,2376,2378,2398,2401,2407,2410,2416,2419,2425,2428,2434,2437,2448,2450,2454,2456,2462,2464,2470,2472,2476,2480,2486,2493,2496,2502,2505,2511,2514,2524,2527,2529,2533,2536,2558,2560,2566,2569,2575,2578,2584,2586,2592,2594,2598,2864,2866,2872,2875,2881,2884,2887,2893,2896,2902,2904,2909,2912,2926,2928,2934,2937,2943,2945,2956,2959,2965,2968,2970,2974,2977,2980,2986,2989,2995,2997,3003,3005,3009,3014,3021,3024,3030,3033,3036,3042,3045,3051,3054,3060,3062,3066,3069,3075,3078,3084,3087,3090,3096,3098,3104,3107,3113,3116,3121,3124,3130,3133,3139,3142,3148,3151,3154,3168,3170,3176,3179,3181,3184,3188,3191,3197,3199,3202,3208,3211,3213,3224,3227,3229,3235,3238,3240,3250,3253,3255,3259,3262,3338,3340,3344,3349,3355,3357,3380,3383,3389,3392,3398,3401,3407,3410,3416,3419,3425,3428,3434,3436,3440,3443,3446,3452,3455,3461,3464,3470,3473,3476,3482,3484,3490,3493,3499,3502,3508,3510,3514,3519,3525,3527,3533,3536,3538,3542,3545,3551,3554,3560,3562,3566,3569,3575,3577,3583,3585,3588,3592,3595,3601,3604,3607,3613,3616,3626,3628,3632,3634,3677,3680,3682,3686,3689,3695,3698,3704,3707,3709,3713,3717,3723,3726,3732,3735,3745,3747,3751,3753,3775,3778,3784,3787,3797,3799,3805,3808,3810,3816,3819,3825,3828,3834,3837,3848,3850,3854,3857,3863,3866,3872,3874,3877,3880,3886,3889,3895,3898,3904,3907,3918,3921,3927],[12,13,14],"p",{},"C++20 在：",[16,17,22],"pre",{"className":18,"code":19,"language":20,"meta":21,"style":21},"language-cpp shiki shiki-themes github-light github-dark","\u003Csemaphore>\n\u003Clatch>\n\u003Cbarrier>\n","cpp","",[23,24,25,41,51],"code",{"__ignoreMap":21},[26,27,30,34,38],"span",{"class":28,"line":29},"line",1,[26,31,33],{"class":32},"szBVR","\u003C",[26,35,37],{"class":36},"sVt8B","semaphore",[26,39,40],{"class":32},">\n",[26,42,44,46,49],{"class":28,"line":43},2,[26,45,33],{"class":32},[26,47,48],{"class":36},"latch",[26,50,40],{"class":32},[26,52,54,56,59],{"class":28,"line":53},3,[26,55,33],{"class":32},[26,57,58],{"class":36},"barrier",[26,60,40],{"class":32},[12,62,63],{},"中加入了几种更高层的同步工具：",[16,65,67],{"className":18,"code":66,"language":20,"meta":21,"style":21},"std::counting_semaphore\nstd::binary_semaphore\nstd::latch\nstd::barrier\n",[23,68,69,78,85,92],{"__ignoreMap":21},[26,70,71,75],{"class":28,"line":29},[26,72,74],{"class":73},"sScJk","std",[26,76,77],{"class":36},"::counting_semaphore\n",[26,79,80,82],{"class":28,"line":43},[26,81,74],{"class":73},[26,83,84],{"class":36},"::binary_semaphore\n",[26,86,87,89],{"class":28,"line":53},[26,88,74],{"class":73},[26,90,91],{"class":36},"::latch\n",[26,93,95,97],{"class":28,"line":94},4,[26,96,74],{"class":73},[26,98,99],{"class":36},"::barrier\n",[12,101,102,103,106],{},"它们和 ",[23,104,105],{},"mutex"," 解决的问题不一样。",[12,108,109],{},"可以先用一句话记住：",[16,111,116],{"className":112,"code":114,"language":115,"meta":21},[113],"language-text","mutex\n→ 一次只允许一个线程进入临界区\n\nsemaphore\n→ 一共有多少张“通行证”\n\nlatch\n→ 等大家一次性全部到齐\n\nbarrier\n→ 每一轮都要等大家到齐后再进入下一轮\n","text",[23,117,114],{"__ignoreMap":21},[12,119,120],{},"所以：",[16,122,125],{"className":123,"code":124,"language":115,"meta":21},[113],"semaphore\n→ 许可数量控制\n\nlatch\n→ 一次性同步\n\nbarrier\n→ 可重复阶段同步\n",[23,126,124],{"__ignoreMap":21},[12,128,129],{},"这些工具很多都可以用：",[16,131,134],{"className":132,"code":133,"language":115,"meta":21},[113],"mutex + condition_variable + counter\n",[23,135,133],{"__ignoreMap":21},[12,137,138],{},"手动实现。",[12,140,141],{},"但既然标准库已经提供了现成抽象，就没必要每次自己重新设计状态、计数和通知协议。",[143,144],"hr",{},[146,147,149],"h2",{"id":148},"semaphore许可数量","semaphore：许可数量",[151,152,154],"h3",{"id":153},"semaphore控制许可数量","semaphore：控制“许可数量”",[151,156,158],{"id":157},"stdcounting_semaphore",[23,159,160],{},"std::counting_semaphore",[12,162,163,165],{},[23,164,160],{}," 内部维护一个计数。",[12,167,168],{},"这个计数可以理解成：",[170,171,172],"blockquote",{},[12,173,174],{},[175,176,177],"strong",{},"当前还有多少张可用通行证。",[12,179,180],{},"例如：",[16,182,185],{"className":183,"code":184,"language":115,"meta":21},[113],"当前计数 = 3\n",[23,186,184],{"__ignoreMap":21},[12,188,189],{},"就可以理解成：",[16,191,194],{"className":192,"code":193,"language":115,"meta":21},[113],"目前还有 3 个线程可以获得许可\n",[23,195,193],{"__ignoreMap":21},[12,197,198],{},"线程想进入受限制区域之前调用：",[16,200,202],{"className":18,"code":201,"language":20,"meta":21,"style":21},"semaphore.acquire();\n",[23,203,204],{"__ignoreMap":21},[26,205,206,209,212],{"class":28,"line":29},[26,207,208],{"class":36},"semaphore.",[26,210,211],{"class":73},"acquire",[26,213,214],{"class":36},"();\n",[12,216,217],{},"如果当前计数：",[16,219,222],{"className":220,"code":221,"language":115,"meta":21},[113],"> 0\n",[23,223,221],{"__ignoreMap":21},[12,225,226],{},"那么：",[16,228,231],{"className":229,"code":230,"language":115,"meta":21},[113],"计数减 1\n线程继续执行\n",[23,232,230],{"__ignoreMap":21},[12,234,217],{},[16,236,239],{"className":237,"code":238,"language":115,"meta":21},[113],"== 0\n",[23,240,238],{"__ignoreMap":21},[12,242,226],{},[16,244,247],{"className":245,"code":246,"language":115,"meta":21},[113],"暂时没有许可\n线程阻塞等待\n",[23,248,246],{"__ignoreMap":21},[12,250,251],{},"等使用完以后：",[16,253,255],{"className":18,"code":254,"language":20,"meta":21,"style":21},"semaphore.release();\n",[23,256,257],{"__ignoreMap":21},[26,258,259,261,264],{"class":28,"line":29},[26,260,208],{"class":36},[26,262,263],{"class":73},"release",[26,265,214],{"class":36},[12,267,268],{},"表示：",[170,270,271],{},[12,272,273],{},[175,274,275],{},"归还一个许可。",[12,277,278],{},"于是：",[16,280,283],{"className":281,"code":282,"language":115,"meta":21},[113],"计数加 1\n",[23,284,282],{"__ignoreMap":21},[12,286,287],{},"并且可能唤醒一个正在等待许可的线程。",[12,289,290],{},"所以 semaphore 最核心的流程就是：",[16,292,295],{"className":293,"code":294,"language":115,"meta":21},[113],"acquire()\n→ 拿一张通行证\n\n执行受限制的工作\n\nrelease()\n→ 把通行证还回去\n",[23,296,294],{"__ignoreMap":21},[143,298],{},[151,300,302],{"id":301},"counting_semaphore-最典型的用途限制并发数量","counting_semaphore 最典型的用途：限制并发数量",[12,304,180],{},[170,306,307],{},[12,308,309],{},"最多只允许 2 个线程同时执行某段任务。",[16,311,313],{"className":18,"code":312,"language":20,"meta":21,"style":21},"#include \u003Cchrono>\n#include \u003Cprint>\n#include \u003Csemaphore>\n#include \u003Cthread>\n#include \u003Cvector>\n\nusing namespace std::chrono_literals;\n\nstd::counting_semaphore\u003C2> slots(2);\n\nvoid worker(int id)\n{\n    slots.acquire();\n\n    std::println(\"start {}\", id);\n\n    std::this_thread::sleep_for(500ms);\n\n    std::println(\"end {}\", id);\n\n    slots.release();\n}\n\nint main()\n{\n    std::vector\u003Cstd::thread> threads;\n\n    for (int i = 0; i \u003C 5; ++i)\n    {\n        threads.emplace_back(worker, i);\n    }\n\n    for (auto& thread : threads)\n    {\n        thread.join();\n    }\n}\n",[23,314,315,324,331,338,345,353,360,381,386,416,421,442,448,458,463,482,487,512,517,533,538,547,553,558,569,574,595,600,637,643,655,661,666,679,684,695,700],{"__ignoreMap":21},[26,316,317,320],{"class":28,"line":29},[26,318,319],{"class":32},"#include",[26,321,323],{"class":322},"sZZnC"," \u003Cchrono>\n",[26,325,326,328],{"class":28,"line":43},[26,327,319],{"class":32},[26,329,330],{"class":322}," \u003Cprint>\n",[26,332,333,335],{"class":28,"line":53},[26,334,319],{"class":32},[26,336,337],{"class":322}," \u003Csemaphore>\n",[26,339,340,342],{"class":28,"line":94},[26,341,319],{"class":32},[26,343,344],{"class":322}," \u003Cthread>\n",[26,346,348,350],{"class":28,"line":347},5,[26,349,319],{"class":32},[26,351,352],{"class":322}," \u003Cvector>\n",[26,354,356],{"class":28,"line":355},6,[26,357,359],{"emptyLinePlaceholder":358},true,"\n",[26,361,363,366,369,372,375,378],{"class":28,"line":362},7,[26,364,365],{"class":32},"using",[26,367,368],{"class":32}," namespace",[26,370,371],{"class":73}," std",[26,373,374],{"class":36},"::",[26,376,377],{"class":73},"chrono_literals",[26,379,380],{"class":36},";\n",[26,382,384],{"class":28,"line":383},8,[26,385,359],{"emptyLinePlaceholder":358},[26,387,389,391,393,396,398,402,405,408,411,413],{"class":28,"line":388},9,[26,390,74],{"class":73},[26,392,374],{"class":36},[26,394,395],{"class":73},"counting_semaphore",[26,397,33],{"class":36},[26,399,401],{"class":400},"sj4cs","2",[26,403,404],{"class":36},"> ",[26,406,407],{"class":73},"slots",[26,409,410],{"class":36},"(",[26,412,401],{"class":400},[26,414,415],{"class":36},");\n",[26,417,419],{"class":28,"line":418},10,[26,420,359],{"emptyLinePlaceholder":358},[26,422,424,427,430,432,435,439],{"class":28,"line":423},11,[26,425,426],{"class":32},"void",[26,428,429],{"class":73}," worker",[26,431,410],{"class":36},[26,433,434],{"class":32},"int",[26,436,438],{"class":437},"s4XuR"," id",[26,440,441],{"class":36},")\n",[26,443,445],{"class":28,"line":444},12,[26,446,447],{"class":36},"{\n",[26,449,451,454,456],{"class":28,"line":450},13,[26,452,453],{"class":36},"    slots.",[26,455,211],{"class":73},[26,457,214],{"class":36},[26,459,461],{"class":28,"line":460},14,[26,462,359],{"emptyLinePlaceholder":358},[26,464,466,469,471,474,476,479],{"class":28,"line":465},15,[26,467,468],{"class":73},"    std",[26,470,374],{"class":36},[26,472,473],{"class":73},"println",[26,475,410],{"class":36},[26,477,478],{"class":322},"\"start {}\"",[26,480,481],{"class":36},", id);\n",[26,483,485],{"class":28,"line":484},16,[26,486,359],{"emptyLinePlaceholder":358},[26,488,490,492,494,497,499,502,504,507,510],{"class":28,"line":489},17,[26,491,468],{"class":73},[26,493,374],{"class":36},[26,495,496],{"class":73},"this_thread",[26,498,374],{"class":36},[26,500,501],{"class":73},"sleep_for",[26,503,410],{"class":36},[26,505,506],{"class":400},"500",[26,508,509],{"class":32},"ms",[26,511,415],{"class":36},[26,513,515],{"class":28,"line":514},18,[26,516,359],{"emptyLinePlaceholder":358},[26,518,520,522,524,526,528,531],{"class":28,"line":519},19,[26,521,468],{"class":73},[26,523,374],{"class":36},[26,525,473],{"class":73},[26,527,410],{"class":36},[26,529,530],{"class":322},"\"end {}\"",[26,532,481],{"class":36},[26,534,536],{"class":28,"line":535},20,[26,537,359],{"emptyLinePlaceholder":358},[26,539,541,543,545],{"class":28,"line":540},21,[26,542,453],{"class":36},[26,544,263],{"class":73},[26,546,214],{"class":36},[26,548,550],{"class":28,"line":549},22,[26,551,552],{"class":36},"}\n",[26,554,556],{"class":28,"line":555},23,[26,557,359],{"emptyLinePlaceholder":358},[26,559,561,563,566],{"class":28,"line":560},24,[26,562,434],{"class":32},[26,564,565],{"class":73}," main",[26,567,568],{"class":36},"()\n",[26,570,572],{"class":28,"line":571},25,[26,573,447],{"class":36},[26,575,577,579,582,584,586,589,592],{"class":28,"line":576},26,[26,578,468],{"class":73},[26,580,581],{"class":36},"::vector",[26,583,33],{"class":32},[26,585,74],{"class":73},[26,587,588],{"class":36},"::thread",[26,590,591],{"class":32},">",[26,593,594],{"class":36}," threads;\n",[26,596,598],{"class":28,"line":597},27,[26,599,359],{"emptyLinePlaceholder":358},[26,601,603,606,609,611,614,617,620,623,625,628,631,634],{"class":28,"line":602},28,[26,604,605],{"class":32},"    for",[26,607,608],{"class":36}," (",[26,610,434],{"class":32},[26,612,613],{"class":36}," i ",[26,615,616],{"class":32},"=",[26,618,619],{"class":400}," 0",[26,621,622],{"class":36},"; i ",[26,624,33],{"class":32},[26,626,627],{"class":400}," 5",[26,629,630],{"class":36},"; ",[26,632,633],{"class":32},"++",[26,635,636],{"class":36},"i)\n",[26,638,640],{"class":28,"line":639},29,[26,641,642],{"class":36},"    {\n",[26,644,646,649,652],{"class":28,"line":645},30,[26,647,648],{"class":36},"        threads.",[26,650,651],{"class":73},"emplace_back",[26,653,654],{"class":36},"(worker, i);\n",[26,656,658],{"class":28,"line":657},31,[26,659,660],{"class":36},"    }\n",[26,662,664],{"class":28,"line":663},32,[26,665,359],{"emptyLinePlaceholder":358},[26,667,669,671,673,676],{"class":28,"line":668},33,[26,670,605],{"class":32},[26,672,608],{"class":36},[26,674,675],{"class":32},"auto&",[26,677,678],{"class":36}," thread : threads)\n",[26,680,682],{"class":28,"line":681},34,[26,683,642],{"class":36},[26,685,687,690,693],{"class":28,"line":686},35,[26,688,689],{"class":36},"        thread.",[26,691,692],{"class":73},"join",[26,694,214],{"class":36},[26,696,698],{"class":28,"line":697},36,[26,699,660],{"class":36},[26,701,703],{"class":28,"line":702},37,[26,704,552],{"class":36},[12,706,707],{},"可能输出：",[16,709,712],{"className":710,"code":711,"language":115,"meta":21},[113],"start 0\nstart 1\nend 0\nstart 2\nend 1\nstart 3\nend 2\nstart 4\nend 3\nend 4\n",[23,713,711],{"__ignoreMap":21},[12,715,716],{},"虽然我们创建了：",[16,718,721],{"className":719,"code":720,"language":115,"meta":21},[113],"5 个线程\n",[23,722,720],{"__ignoreMap":21},[12,724,725],{},"但：",[16,727,729],{"className":18,"code":728,"language":20,"meta":21,"style":21},"std::counting_semaphore\u003C2> slots(2);\n",[23,730,731],{"__ignoreMap":21},[26,732,733,735,737,739,741,743,745,747,749,751],{"class":28,"line":29},[26,734,74],{"class":73},[26,736,374],{"class":36},[26,738,395],{"class":73},[26,740,33],{"class":36},[26,742,401],{"class":400},[26,744,404],{"class":36},[26,746,407],{"class":73},[26,748,410],{"class":36},[26,750,401],{"class":400},[26,752,415],{"class":36},[12,754,755],{},"初始只有 2 个许可。",[12,757,758],{},"所以最多只有：",[16,760,763],{"className":761,"code":762,"language":115,"meta":21},[113],"2 个线程\n",[23,764,762],{"__ignoreMap":21},[12,766,767],{},"能同时处于：",[16,769,771],{"className":18,"code":770,"language":20,"meta":21,"style":21},"slots.acquire();\n...\nslots.release();\n",[23,772,773,782,787],{"__ignoreMap":21},[26,774,775,778,780],{"class":28,"line":29},[26,776,777],{"class":36},"slots.",[26,779,211],{"class":73},[26,781,214],{"class":36},[26,783,784],{"class":28,"line":43},[26,785,786],{"class":36},"...\n",[26,788,789,791,793],{"class":28,"line":53},[26,790,777],{"class":36},[26,792,263],{"class":73},[26,794,214],{"class":36},[12,796,797],{},"之间。",[12,799,800],{},"可以理解成：",[16,802,805],{"className":803,"code":804,"language":115,"meta":21},[113],"一开始有 2 张通行证\n\n线程 A 拿走一张\n剩 1 张\n\n线程 B 拿走一张\n剩 0 张\n\n线程 C 来了\n没票\n只能等\n\nA 或 B 归还一张\n↓\nC 获得许可继续\n",[23,806,804],{"__ignoreMap":21},[143,808],{},[151,810,812],{"id":811},"semaphore-和-mutex-最大的区别","semaphore 和 mutex 最大的区别",[12,814,815,817],{},[23,816,105],{}," 通常表达：",[170,819,820],{},[12,821,822],{},[175,823,824],{},"同一时刻只能有一个线程进入临界区。",[12,826,827],{},"而：",[16,829,831],{"className":18,"code":830,"language":20,"meta":21,"style":21},"std::counting_semaphore\u003CN>\n",[23,832,833],{"__ignoreMap":21},[26,834,835,837,840,842,845],{"class":28,"line":29},[26,836,74],{"class":73},[26,838,839],{"class":36},"::counting_semaphore",[26,841,33],{"class":32},[26,843,844],{"class":36},"N",[26,846,40],{"class":32},[12,848,849],{},"可以表达：",[170,851,852],{},[12,853,854],{},[175,855,856],{},"同一时刻最多允许 N 个线程进入。",[12,858,120],{},[16,860,863],{"className":861,"code":862,"language":115,"meta":21},[113],"mutex\n≈ 只有 1 把钥匙\n\ncounting_semaphore\n≈ 有 N 张通行证\n",[23,864,862],{"__ignoreMap":21},[12,866,867],{},"但它们还有一个更重要的语义区别：",[16,869,872],{"className":870,"code":871,"language":115,"meta":21},[113],"mutex\n→ 强调锁的所有权\n\nsemaphore\n→ 强调许可数量\n",[23,873,871],{"__ignoreMap":21},[12,875,876],{},"对于 mutex：",[16,878,881],{"className":879,"code":880,"language":115,"meta":21},[113],"谁 lock\n通常就应该由谁 unlock\n",[23,882,880],{"__ignoreMap":21},[12,884,885],{},"而 semaphore：",[16,887,890],{"className":888,"code":889,"language":115,"meta":21},[113],"谁 acquire\n不要求必须由同一个线程 release\n",[23,891,889],{"__ignoreMap":21},[12,893,894],{},"也就是说：",[170,896,897],{},[12,898,899],{},"semaphore 的许可可以由一个线程获取，由另一个线程归还。",[12,901,902],{},"这使它不仅可以限制并发数量，也可以做线程间信号通知。",[143,904],{},[151,906,907],{"id":907},"模板参数和初始计数不是一回事",[12,909,180],{},[16,911,913],{"className":18,"code":912,"language":20,"meta":21,"style":21},"std::counting_semaphore\u003C10> semaphore(3);\n",[23,914,915],{"__ignoreMap":21},[26,916,917,919,921,923,925,928,930,932,934,937],{"class":28,"line":29},[26,918,74],{"class":73},[26,920,374],{"class":36},[26,922,395],{"class":73},[26,924,33],{"class":36},[26,926,927],{"class":400},"10",[26,929,404],{"class":36},[26,931,37],{"class":73},[26,933,410],{"class":36},[26,935,936],{"class":400},"3",[26,938,415],{"class":36},[12,940,941],{},"这里：",[16,943,946],{"className":944,"code":945,"language":115,"meta":21},[113],"10\n",[23,947,945],{"__ignoreMap":21},[12,949,950],{},"不是：",[16,952,955],{"className":953,"code":954,"language":115,"meta":21},[113],"当前有 10 个许可\n",[23,956,954],{"__ignoreMap":21},[12,958,959],{},"它表示的是：",[170,961,962],{},[12,963,964],{},[175,965,966],{},"这个 semaphore 所支持的最大计数上界至少为 10。",[12,968,827],{},[16,970,973],{"className":971,"code":972,"language":115,"meta":21},[113],"3\n",[23,974,972],{"__ignoreMap":21},[12,976,977],{},"才是：",[170,979,980],{},[12,981,982],{},[175,983,984],{},"初始计数。",[12,986,987],{},"所以这个对象刚创建时：",[16,989,991],{"className":18,"code":990,"language":20,"meta":21,"style":21},"semaphore.acquire();\nsemaphore.acquire();\nsemaphore.acquire();\n",[23,992,993,1001,1009],{"__ignoreMap":21},[26,994,995,997,999],{"class":28,"line":29},[26,996,208],{"class":36},[26,998,211],{"class":73},[26,1000,214],{"class":36},[26,1002,1003,1005,1007],{"class":28,"line":43},[26,1004,208],{"class":36},[26,1006,211],{"class":73},[26,1008,214],{"class":36},[26,1010,1011,1013,1015],{"class":28,"line":53},[26,1012,208],{"class":36},[26,1014,211],{"class":73},[26,1016,214],{"class":36},[12,1018,1019],{},"前三次可以直接成功。",[12,1021,1022],{},"第四次：",[16,1024,1025],{"className":18,"code":201,"language":20,"meta":21,"style":21},[23,1026,1027],{"__ignoreMap":21},[26,1028,1029,1031,1033],{"class":28,"line":29},[26,1030,208],{"class":36},[26,1032,211],{"class":73},[26,1034,214],{"class":36},[12,1036,1037],{},"就需要等待别人：",[16,1039,1040],{"className":18,"code":254,"language":20,"meta":21,"style":21},[23,1041,1042],{"__ignoreMap":21},[26,1043,1044,1046,1048],{"class":28,"line":29},[26,1045,208],{"class":36},[26,1047,263],{"class":73},[26,1049,214],{"class":36},[12,1051,1052],{},"所以记住：",[16,1054,1057],{"className":1055,"code":1056,"language":115,"meta":21},[113],"std::counting_semaphore\u003C10> semaphore(3);\n\n10\n→ 计数上限相关参数\n\n3\n→ 当前初始许可数量\n",[23,1058,1056],{"__ignoreMap":21},[12,1060,1061],{},"不要把它们混在一起。",[143,1063],{},[151,1065,1067],{"id":1066},"try_acquire",[23,1068,1069],{},"try_acquire()",[12,1071,1072],{},"如果你不想：",[16,1074,1077],{"className":1075,"code":1076,"language":115,"meta":21},[113],"没有许可就一直阻塞\n",[23,1078,1076],{"__ignoreMap":21},[12,1080,1081],{},"可以用：",[16,1083,1085],{"className":18,"code":1084,"language":20,"meta":21,"style":21},"if (semaphore.try_acquire())\n{\n    \u002F\u002F 成功获得许可\n\n    semaphore.release();\n}\n",[23,1086,1087,1100,1104,1110,1114,1123],{"__ignoreMap":21},[26,1088,1089,1092,1095,1097],{"class":28,"line":29},[26,1090,1091],{"class":32},"if",[26,1093,1094],{"class":36}," (semaphore.",[26,1096,1066],{"class":73},[26,1098,1099],{"class":36},"())\n",[26,1101,1102],{"class":28,"line":43},[26,1103,447],{"class":36},[26,1105,1106],{"class":28,"line":53},[26,1107,1109],{"class":1108},"sJ8bj","    \u002F\u002F 成功获得许可\n",[26,1111,1112],{"class":28,"line":94},[26,1113,359],{"emptyLinePlaceholder":358},[26,1115,1116,1119,1121],{"class":28,"line":347},[26,1117,1118],{"class":36},"    semaphore.",[26,1120,263],{"class":73},[26,1122,214],{"class":36},[26,1124,1125],{"class":28,"line":355},[26,1126,552],{"class":36},[12,1128,1129],{},"它的逻辑是：",[16,1131,1134],{"className":1132,"code":1133,"language":115,"meta":21},[113],"有许可\n→ 拿走一个\n→ 返回 true\n\n没许可\n→ 立刻返回 false\n→ 不等待\n",[23,1135,1133],{"__ignoreMap":21},[12,1137,1138],{},"这和：",[16,1140,1142],{"className":18,"code":1141,"language":20,"meta":21,"style":21},"mutex.try_lock();\n",[23,1143,1144],{"__ignoreMap":21},[26,1145,1146,1149,1152],{"class":28,"line":29},[26,1147,1148],{"class":36},"mutex.",[26,1150,1151],{"class":73},"try_lock",[26,1153,214],{"class":36},[12,1155,1156],{},"很像。",[143,1158],{},[151,1160,1162],{"id":1161},"带超时的-acquire","带超时的 acquire",[12,1164,1165],{},"还可以：",[16,1167,1169],{"className":18,"code":1168,"language":20,"meta":21,"style":21},"semaphore.try_acquire_for(...);\n",[23,1170,1171],{"__ignoreMap":21},[26,1172,1173,1175,1178],{"class":28,"line":29},[26,1174,208],{"class":36},[26,1176,1177],{"class":73},"try_acquire_for",[26,1179,1180],{"class":36},"(...);\n",[12,1182,1183],{},"或者：",[16,1185,1187],{"className":18,"code":1186,"language":20,"meta":21,"style":21},"semaphore.try_acquire_until(...);\n",[23,1188,1189],{"__ignoreMap":21},[26,1190,1191,1193,1196],{"class":28,"line":29},[26,1192,208],{"class":36},[26,1194,1195],{"class":73},"try_acquire_until",[26,1197,1180],{"class":36},[12,1199,800],{},[16,1201,1204],{"className":1202,"code":1203,"language":115,"meta":21},[113],"try_acquire_for()\n→ 最多等一段时间\n\ntry_acquire_until()\n→ 最多等到某个时间点\n",[23,1205,1203],{"__ignoreMap":21},[12,1207,180],{},[16,1209,1212],{"className":1210,"code":1211,"language":115,"meta":21},[113],"最多等 100ms\n\n拿到许可\n→ 继续\n\n100ms 还没拿到\n→ 返回失败\n→ 执行备用逻辑\n",[23,1213,1211],{"__ignoreMap":21},[12,1215,1216],{},"适合：",[16,1218,1221],{"className":1219,"code":1220,"language":115,"meta":21},[113],"资源池暂时没资源\n\n连接数已满\n\n并发额度暂时耗尽\n\n不能无限等待\n",[23,1222,1220],{"__ignoreMap":21},[12,1224,1225],{},"这类场景。",[143,1227],{},[151,1229,1231],{"id":1230},"stdbinary_semaphore",[23,1232,1233],{},"std::binary_semaphore",[12,1235,1236],{},"C++20 还提供：",[16,1238,1240],{"className":18,"code":1239,"language":20,"meta":21,"style":21},"std::binary_semaphore\n",[23,1241,1242],{"__ignoreMap":21},[26,1243,1244,1246],{"class":28,"line":29},[26,1245,74],{"class":73},[26,1247,84],{"class":36},[12,1249,1250],{},"它可以理解成：",[170,1252,1253],{},[12,1254,1255],{},[175,1256,1257],{},"计数最多只有 1 的 semaphore。",[12,1259,1260],{},"也就是它只有两种状态：",[16,1262,1265],{"className":1263,"code":1264,"language":115,"meta":21},[113],"0\n→ 没有许可\n\n1\n→ 有一个许可\n",[23,1266,1264],{"__ignoreMap":21},[12,1268,180],{},[16,1270,1272],{"className":18,"code":1271,"language":20,"meta":21,"style":21},"std::binary_semaphore signal(0);\n",[23,1273,1274],{"__ignoreMap":21},[26,1275,1276,1278,1280,1283,1286,1288,1291],{"class":28,"line":29},[26,1277,74],{"class":73},[26,1279,374],{"class":36},[26,1281,1282],{"class":73},"binary_semaphore",[26,1284,1285],{"class":73}," signal",[26,1287,410],{"class":36},[26,1289,1290],{"class":400},"0",[26,1292,415],{"class":36},[12,1294,1295],{},"初始：",[16,1297,1300],{"className":1298,"code":1299,"language":115,"meta":21},[113],"0 个许可\n",[23,1301,1299],{"__ignoreMap":21},[12,1303,120],{},[16,1305,1307],{"className":18,"code":1306,"language":20,"meta":21,"style":21},"signal.acquire();\n",[23,1308,1309],{"__ignoreMap":21},[26,1310,1311,1314,1316],{"class":28,"line":29},[26,1312,1313],{"class":36},"signal.",[26,1315,211],{"class":73},[26,1317,214],{"class":36},[12,1319,1320],{},"会阻塞。",[12,1322,1323],{},"另一个线程执行：",[16,1325,1327],{"className":18,"code":1326,"language":20,"meta":21,"style":21},"signal.release();\n",[23,1328,1329],{"__ignoreMap":21},[26,1330,1331,1333,1335],{"class":28,"line":29},[26,1332,1313],{"class":36},[26,1334,263],{"class":73},[26,1336,214],{"class":36},[12,1338,1339],{},"以后：",[16,1341,1344],{"className":1342,"code":1343,"language":115,"meta":21},[113],"许可变成 1\n↓\n一个等待线程可以继续\n",[23,1345,1343],{"__ignoreMap":21},[143,1347],{},[151,1349,1351],{"id":1350},"binary_semaphore-可以理解成一个门","binary_semaphore 可以理解成一个“门”",[12,1353,180],{},[16,1355,1356],{"className":18,"code":1271,"language":20,"meta":21,"style":21},[23,1357,1358],{"__ignoreMap":21},[26,1359,1360,1362,1364,1366,1368,1370,1372],{"class":28,"line":29},[26,1361,74],{"class":73},[26,1363,374],{"class":36},[26,1365,1282],{"class":73},[26,1367,1285],{"class":73},[26,1369,410],{"class":36},[26,1371,1290],{"class":400},[26,1373,415],{"class":36},[12,1375,1376],{},"可以想成：",[16,1378,1381],{"className":1379,"code":1380,"language":115,"meta":21},[113],"门一开始是关着的\n",[23,1382,1380],{"__ignoreMap":21},[12,1384,1385],{},"线程 A：",[16,1387,1388],{"className":18,"code":1306,"language":20,"meta":21,"style":21},[23,1389,1390],{"__ignoreMap":21},[26,1391,1392,1394,1396],{"class":28,"line":29},[26,1393,1313],{"class":36},[26,1395,211],{"class":73},[26,1397,214],{"class":36},[12,1399,1400],{},"相当于：",[16,1402,1405],{"className":1403,"code":1404,"language":115,"meta":21},[113],"门没开\n→ 在门口等\n",[23,1406,1404],{"__ignoreMap":21},[12,1408,1409],{},"线程 B：",[16,1411,1412],{"className":18,"code":1326,"language":20,"meta":21,"style":21},[23,1413,1414],{"__ignoreMap":21},[26,1415,1416,1418,1420],{"class":28,"line":29},[26,1417,1313],{"class":36},[26,1419,263],{"class":73},[26,1421,214],{"class":36},[12,1423,1400],{},[16,1425,1428],{"className":1426,"code":1427,"language":115,"meta":21},[113],"发放一个许可\n→ 让一个等待线程通过\n",[23,1429,1427],{"__ignoreMap":21},[12,1431,1432],{},"所以 binary semaphore 很适合表达：",[16,1434,1437],{"className":1435,"code":1436,"language":115,"meta":21},[113],"线程 A 等一个信号\n\n线程 B 发出信号\n",[23,1438,1436],{"__ignoreMap":21},[143,1440],{},[151,1442,1444],{"id":1443},"binary_semaphore-不是-mutex","binary_semaphore 不是 mutex",[12,1446,1447],{},"虽然 binary semaphore 的计数最多为 1，看起来很像：",[16,1449,1451],{"className":18,"code":1450,"language":20,"meta":21,"style":21},"std::mutex\n",[23,1452,1453],{"__ignoreMap":21},[26,1454,1455,1457],{"class":28,"line":29},[26,1456,74],{"class":73},[26,1458,1459],{"class":36},"::mutex\n",[12,1461,1462],{},"但它们不是一回事。",[12,1464,1465,1467],{},[23,1466,105],{},"：",[16,1469,1472],{"className":1470,"code":1471,"language":115,"meta":21},[113],"强调所有权\n\n哪个线程获得锁\n通常由哪个线程释放\n",[23,1473,1471],{"__ignoreMap":21},[12,1475,1476,1477,1467],{},"而 ",[23,1478,1282],{},[16,1480,1483],{"className":1481,"code":1482,"language":115,"meta":21},[113],"强调“有没有许可”\n\n释放许可的线程\n可以不是 acquire 的那个线程\n",[23,1484,1482],{"__ignoreMap":21},[12,1486,1487],{},"可以这样记：",[16,1489,1492],{"className":1490,"code":1491,"language":115,"meta":21},[113],"mutex\n→ 谁锁门，谁开门\n\nsemaphore\n→ 系统里有几张通行证\n",[23,1493,1491],{"__ignoreMap":21},[12,1495,1496],{},"所以不要因为：",[16,1498,1501],{"className":1499,"code":1500,"language":115,"meta":21},[113],"binary_semaphore 的值只有 0 \u002F 1\n",[23,1502,1500],{"__ignoreMap":21},[12,1504,1505],{},"就把它当成 mutex 的完全替代品。",[143,1507],{},[151,1509,1511],{"id":1510},"semaphore-不会自动让共享对象线程安全","semaphore 不会自动让共享对象线程安全",[12,1513,180],{},[16,1515,1517],{"className":18,"code":1516,"language":20,"meta":21,"style":21},"std::vector\u003Cint> data;\n",[23,1518,1519],{"__ignoreMap":21},[26,1520,1521,1523,1525,1528],{"class":28,"line":29},[26,1522,74],{"class":73},[26,1524,581],{"class":36},[26,1526,1527],{"class":32},"\u003Cint>",[26,1529,1530],{"class":36}," data;\n",[12,1532,1533],{},"多个线程同时：",[16,1535,1537],{"className":18,"code":1536,"language":20,"meta":21,"style":21},"data.push_back(...);\n",[23,1538,1539],{"__ignoreMap":21},[26,1540,1541,1544,1547],{"class":28,"line":29},[26,1542,1543],{"class":36},"data.",[26,1545,1546],{"class":73},"push_back",[26,1548,1180],{"class":36},[12,1550,1551],{},"可能产生数据竞争。",[12,1553,1554],{},"即使你用了：",[16,1556,1558],{"className":18,"code":1557,"language":20,"meta":21,"style":21},"std::counting_semaphore\u003C4> semaphore(4);\n",[23,1559,1560],{"__ignoreMap":21},[26,1561,1562,1564,1566,1568,1570,1573,1575,1577,1579,1581],{"class":28,"line":29},[26,1563,74],{"class":73},[26,1565,374],{"class":36},[26,1567,395],{"class":73},[26,1569,33],{"class":36},[26,1571,1572],{"class":400},"4",[26,1574,404],{"class":36},[26,1576,37],{"class":73},[26,1578,410],{"class":36},[26,1580,1572],{"class":400},[26,1582,415],{"class":36},[12,1584,1585],{},"它也不会神奇地让：",[16,1587,1589],{"className":18,"code":1588,"language":20,"meta":21,"style":21},"std::vector\n",[23,1590,1591],{"__ignoreMap":21},[26,1592,1593,1595],{"class":28,"line":29},[26,1594,74],{"class":73},[26,1596,1597],{"class":36},"::vector\n",[12,1599,1600],{},"变成线程安全。",[12,1602,1603],{},"semaphore 只解决：",[16,1605,1608],{"className":1606,"code":1607,"language":115,"meta":21},[113],"最多允许多少个线程获得许可\n",[23,1609,1607],{"__ignoreMap":21},[12,1611,1612],{},"并不自动解决：",[16,1614,1617],{"className":1615,"code":1616,"language":115,"meta":21},[113],"共享对象的一致性保护\n",[23,1618,1616],{"__ignoreMap":21},[12,1620,1621],{},"所以很常见的组合是：",[16,1623,1626],{"className":1624,"code":1625,"language":115,"meta":21},[113],"semaphore\n→ 控制最多多少个任务同时运行\n\nmutex\n→ 保护任务访问的共享数据结构\n",[23,1627,1625],{"__ignoreMap":21},[12,1629,1630],{},"两者职责完全不同。",[143,1632],{},[151,1634,1636],{"id":1635},"acquire-以后一定要记得-release","acquire 以后一定要记得 release",[12,1638,180],{},[16,1640,1642],{"className":18,"code":1641,"language":20,"meta":21,"style":21},"semaphore.acquire();\n\n\u002F\u002F 工作\n\nsemaphore.release();\n",[23,1643,1644,1652,1656,1661,1665],{"__ignoreMap":21},[26,1645,1646,1648,1650],{"class":28,"line":29},[26,1647,208],{"class":36},[26,1649,211],{"class":73},[26,1651,214],{"class":36},[26,1653,1654],{"class":28,"line":43},[26,1655,359],{"emptyLinePlaceholder":358},[26,1657,1658],{"class":28,"line":53},[26,1659,1660],{"class":1108},"\u002F\u002F 工作\n",[26,1662,1663],{"class":28,"line":94},[26,1664,359],{"emptyLinePlaceholder":358},[26,1666,1667,1669,1671],{"class":28,"line":347},[26,1668,208],{"class":36},[26,1670,263],{"class":73},[26,1672,214],{"class":36},[12,1674,1675],{},"如果中间发生：",[16,1677,1680],{"className":1678,"code":1679,"language":115,"meta":21},[113],"return\n\n异常\n\n复杂分支\n",[23,1681,1679],{"__ignoreMap":21},[12,1683,1684],{},"导致：",[16,1686,1688],{"className":18,"code":1687,"language":20,"meta":21,"style":21},"release()\n",[23,1689,1690],{"__ignoreMap":21},[26,1691,1692,1694],{"class":28,"line":29},[26,1693,263],{"class":73},[26,1695,568],{"class":36},[12,1697,1698],{},"没有执行，那么：",[16,1700,1703],{"className":1701,"code":1702,"language":115,"meta":21},[113],"许可被拿走以后永远没有归还\n",[23,1704,1702],{"__ignoreMap":21},[12,1706,1707],{},"可用许可会越来越少。",[12,1709,1710],{},"例如本来：",[16,1712,1715],{"className":1713,"code":1714,"language":115,"meta":21},[113],"2 个许可\n",[23,1716,1714],{"__ignoreMap":21},[12,1718,1719],{},"漏掉一次 release 后：",[16,1721,1724],{"className":1722,"code":1723,"language":115,"meta":21},[113],"永远只剩 1 个\n",[23,1725,1723],{"__ignoreMap":21},[12,1727,1728],{},"再漏一次：",[16,1730,1733],{"className":1731,"code":1732,"language":115,"meta":21},[113],"永远变成 0\n",[23,1734,1732],{"__ignoreMap":21},[12,1736,1737],{},"后续线程全部可能卡住。",[12,1739,1740],{},"所以 semaphore 也要认真考虑：",[16,1742,1745],{"className":1743,"code":1744,"language":115,"meta":21},[113],"异常安全\n\n提前 return\n\n许可归还\n",[23,1746,1744],{"__ignoreMap":21},[143,1748],{},[146,1750,1752],{"id":1751},"latch一次性同步","latch：一次性同步",[151,1754,1756],{"id":1755},"latch一次性倒计时同步","latch：一次性倒计时同步",[12,1758,1759,1762],{},[23,1760,1761],{},"std::latch"," 可以理解成：",[170,1764,1765],{},[12,1766,1767],{},[175,1768,1769],{},"一个只能使用一次的倒计时门。",[12,1771,180],{},[16,1773,1775],{"className":18,"code":1774,"language":20,"meta":21,"style":21},"std::latch done(3);\n",[23,1776,1777],{"__ignoreMap":21},[26,1778,1779,1781,1783,1785,1788,1790,1792],{"class":28,"line":29},[26,1780,74],{"class":73},[26,1782,374],{"class":36},[26,1784,48],{"class":73},[26,1786,1787],{"class":73}," done",[26,1789,410],{"class":36},[26,1791,936],{"class":400},[26,1793,415],{"class":36},[12,1795,268],{},[16,1797,1800],{"className":1798,"code":1799,"language":115,"meta":21},[113],"初始计数 = 3\n",[23,1801,1799],{"__ignoreMap":21},[12,1803,1804],{},"每完成一个参与者：",[16,1806,1808],{"className":18,"code":1807,"language":20,"meta":21,"style":21},"done.count_down();\n",[23,1809,1810],{"__ignoreMap":21},[26,1811,1812,1815,1818],{"class":28,"line":29},[26,1813,1814],{"class":36},"done.",[26,1816,1817],{"class":73},"count_down",[26,1819,214],{"class":36},[12,1821,1822],{},"计数减 1。",[12,1824,1825],{},"过程类似：",[16,1827,1830],{"className":1828,"code":1829,"language":115,"meta":21},[113],"3\n↓\n2\n↓\n1\n↓\n0\n",[23,1831,1829],{"__ignoreMap":21},[12,1833,1834],{},"当计数变成：",[16,1836,1839],{"className":1837,"code":1838,"language":115,"meta":21},[113],"0\n",[23,1840,1838],{"__ignoreMap":21},[12,1842,1843],{},"等待 latch 的线程就可以继续。",[143,1845],{},[151,1847,1849],{"id":1848},"latch-最适合表达什么","latch 最适合表达什么",[12,1851,1852],{},"它最适合这种需求：",[170,1854,1855],{},[12,1856,1857],{},[175,1858,1859],{},"等 N 件事情全部做完，然后继续。",[12,1861,180],{},[16,1863,1866],{"className":1864,"code":1865,"language":115,"meta":21},[113],"启动 3 个初始化任务\n\n任务 1 完成\n→ count_down()\n\n任务 2 完成\n→ count_down()\n\n任务 3 完成\n→ count_down()\n\n计数变成 0\n↓\n主线程继续\n",[23,1867,1865],{"__ignoreMap":21},[143,1869],{},[151,1871,1873],{"id":1872},"latch-示例","latch 示例",[16,1875,1877],{"className":18,"code":1876,"language":20,"meta":21,"style":21},"#include \u003Clatch>\n#include \u003Cprint>\n#include \u003Cthread>\n#include \u003Cvector>\n\nstd::latch done(3);\n\nvoid worker(int id)\n{\n    std::println(\"worker {} done\", id);\n\n    done.count_down();\n}\n\nint main()\n{\n    std::vector\u003Cstd::thread> threads;\n\n    for (int i = 0; i \u003C 3; ++i)\n    {\n        threads.emplace_back(worker, i);\n    }\n\n    done.wait();\n\n    std::println(\"all workers reached the latch\");\n\n    for (auto& thread : threads)\n    {\n        thread.join();\n    }\n}\n",[23,1878,1879,1886,1892,1898,1904,1908,1924,1928,1942,1946,1961,1965,1974,1978,1982,1990,1994,2010,2014,2041,2045,2053,2057,2061,2070,2074,2089,2093,2103,2107,2115,2119],{"__ignoreMap":21},[26,1880,1881,1883],{"class":28,"line":29},[26,1882,319],{"class":32},[26,1884,1885],{"class":322}," \u003Clatch>\n",[26,1887,1888,1890],{"class":28,"line":43},[26,1889,319],{"class":32},[26,1891,330],{"class":322},[26,1893,1894,1896],{"class":28,"line":53},[26,1895,319],{"class":32},[26,1897,344],{"class":322},[26,1899,1900,1902],{"class":28,"line":94},[26,1901,319],{"class":32},[26,1903,352],{"class":322},[26,1905,1906],{"class":28,"line":347},[26,1907,359],{"emptyLinePlaceholder":358},[26,1909,1910,1912,1914,1916,1918,1920,1922],{"class":28,"line":355},[26,1911,74],{"class":73},[26,1913,374],{"class":36},[26,1915,48],{"class":73},[26,1917,1787],{"class":73},[26,1919,410],{"class":36},[26,1921,936],{"class":400},[26,1923,415],{"class":36},[26,1925,1926],{"class":28,"line":362},[26,1927,359],{"emptyLinePlaceholder":358},[26,1929,1930,1932,1934,1936,1938,1940],{"class":28,"line":383},[26,1931,426],{"class":32},[26,1933,429],{"class":73},[26,1935,410],{"class":36},[26,1937,434],{"class":32},[26,1939,438],{"class":437},[26,1941,441],{"class":36},[26,1943,1944],{"class":28,"line":388},[26,1945,447],{"class":36},[26,1947,1948,1950,1952,1954,1956,1959],{"class":28,"line":418},[26,1949,468],{"class":73},[26,1951,374],{"class":36},[26,1953,473],{"class":73},[26,1955,410],{"class":36},[26,1957,1958],{"class":322},"\"worker {} done\"",[26,1960,481],{"class":36},[26,1962,1963],{"class":28,"line":423},[26,1964,359],{"emptyLinePlaceholder":358},[26,1966,1967,1970,1972],{"class":28,"line":444},[26,1968,1969],{"class":36},"    done.",[26,1971,1817],{"class":73},[26,1973,214],{"class":36},[26,1975,1976],{"class":28,"line":450},[26,1977,552],{"class":36},[26,1979,1980],{"class":28,"line":460},[26,1981,359],{"emptyLinePlaceholder":358},[26,1983,1984,1986,1988],{"class":28,"line":465},[26,1985,434],{"class":32},[26,1987,565],{"class":73},[26,1989,568],{"class":36},[26,1991,1992],{"class":28,"line":484},[26,1993,447],{"class":36},[26,1995,1996,1998,2000,2002,2004,2006,2008],{"class":28,"line":489},[26,1997,468],{"class":73},[26,1999,581],{"class":36},[26,2001,33],{"class":32},[26,2003,74],{"class":73},[26,2005,588],{"class":36},[26,2007,591],{"class":32},[26,2009,594],{"class":36},[26,2011,2012],{"class":28,"line":514},[26,2013,359],{"emptyLinePlaceholder":358},[26,2015,2016,2018,2020,2022,2024,2026,2028,2030,2032,2035,2037,2039],{"class":28,"line":519},[26,2017,605],{"class":32},[26,2019,608],{"class":36},[26,2021,434],{"class":32},[26,2023,613],{"class":36},[26,2025,616],{"class":32},[26,2027,619],{"class":400},[26,2029,622],{"class":36},[26,2031,33],{"class":32},[26,2033,2034],{"class":400}," 3",[26,2036,630],{"class":36},[26,2038,633],{"class":32},[26,2040,636],{"class":36},[26,2042,2043],{"class":28,"line":535},[26,2044,642],{"class":36},[26,2046,2047,2049,2051],{"class":28,"line":540},[26,2048,648],{"class":36},[26,2050,651],{"class":73},[26,2052,654],{"class":36},[26,2054,2055],{"class":28,"line":549},[26,2056,660],{"class":36},[26,2058,2059],{"class":28,"line":555},[26,2060,359],{"emptyLinePlaceholder":358},[26,2062,2063,2065,2068],{"class":28,"line":560},[26,2064,1969],{"class":36},[26,2066,2067],{"class":73},"wait",[26,2069,214],{"class":36},[26,2071,2072],{"class":28,"line":571},[26,2073,359],{"emptyLinePlaceholder":358},[26,2075,2076,2078,2080,2082,2084,2087],{"class":28,"line":576},[26,2077,468],{"class":73},[26,2079,374],{"class":36},[26,2081,473],{"class":73},[26,2083,410],{"class":36},[26,2085,2086],{"class":322},"\"all workers reached the latch\"",[26,2088,415],{"class":36},[26,2090,2091],{"class":28,"line":597},[26,2092,359],{"emptyLinePlaceholder":358},[26,2094,2095,2097,2099,2101],{"class":28,"line":602},[26,2096,605],{"class":32},[26,2098,608],{"class":36},[26,2100,675],{"class":32},[26,2102,678],{"class":36},[26,2104,2105],{"class":28,"line":639},[26,2106,642],{"class":36},[26,2108,2109,2111,2113],{"class":28,"line":645},[26,2110,689],{"class":36},[26,2112,692],{"class":73},[26,2114,214],{"class":36},[26,2116,2117],{"class":28,"line":657},[26,2118,660],{"class":36},[26,2120,2121],{"class":28,"line":663},[26,2122,552],{"class":36},[12,2124,707],{},[16,2126,2129],{"className":2127,"code":2128,"language":115,"meta":21},[113],"worker 1 done\nworker 0 done\nworker 2 done\nall workers reached the latch\n",[23,2130,2128],{"__ignoreMap":21},[12,2132,2133],{},"前三行顺序不确定。",[12,2135,725],{},[16,2137,2140],{"className":2138,"code":2139,"language":115,"meta":21},[113],"all workers reached the latch\n",[23,2141,2139],{"__ignoreMap":21},[12,2143,2144],{},"一定发生在：",[16,2146,2149],{"className":2147,"code":2148,"language":115,"meta":21},[113],"3 次 count_down()\n",[23,2150,2148],{"__ignoreMap":21},[12,2152,2153],{},"全部完成以后。",[12,2155,2156],{},"所以主线程根本不关心：",[16,2158,2161],{"className":2159,"code":2160,"language":115,"meta":21},[113],"哪个 worker 先完成\n",[23,2162,2160],{"__ignoreMap":21},[12,2164,2165],{},"它只关心：",[16,2167,2170],{"className":2168,"code":2169,"language":115,"meta":21},[113],"计数归零了吗？\n",[23,2171,2169],{"__ignoreMap":21},[143,2173],{},[151,2175,2176],{"id":1817},[23,2177,2178],{},"count_down()",[16,2180,2181],{"className":18,"code":1807,"language":20,"meta":21,"style":21},[23,2182,2183],{"__ignoreMap":21},[26,2184,2185,2187,2189],{"class":28,"line":29},[26,2186,1814],{"class":36},[26,2188,1817],{"class":73},[26,2190,214],{"class":36},[12,2192,268],{},[170,2194,2195],{},[12,2196,2197],{},[175,2198,2199],{},"我完成了自己的这一份工作，把计数减掉。",[12,2201,180],{},[16,2203,2206],{"className":2204,"code":2205,"language":115,"meta":21},[113],"初始 3\n\n第一个线程 count_down()\n→ 2\n\n第二个线程 count_down()\n→ 1\n\n第三个线程 count_down()\n→ 0\n",[23,2207,2205],{"__ignoreMap":21},[12,2209,2210],{},"当计数到：",[16,2212,2214],{"className":2213,"code":1838,"language":115,"meta":21},[113],[23,2215,1838],{"__ignoreMap":21},[12,2217,2218],{},"latch 被永久打开。",[143,2220],{},[151,2222,2223],{"id":2067},[23,2224,2225],{},"wait()",[16,2227,2229],{"className":18,"code":2228,"language":20,"meta":21,"style":21},"done.wait();\n",[23,2230,2231],{"__ignoreMap":21},[26,2232,2233,2235,2237],{"class":28,"line":29},[26,2234,1814],{"class":36},[26,2236,2067],{"class":73},[26,2238,214],{"class":36},[12,2240,268],{},[170,2242,2243],{},[12,2244,2245],{},[175,2246,2247],{},"如果 latch 计数还没有归零，就等待。",[12,2249,2250],{},"如果此时：",[16,2252,2255],{"className":2253,"code":2254,"language":115,"meta":21},[113],"count > 0\n",[23,2256,2254],{"__ignoreMap":21},[12,2258,2259],{},"线程阻塞。",[12,2261,2262],{},"如果已经：",[16,2264,2267],{"className":2265,"code":2266,"language":115,"meta":21},[113],"count == 0\n",[23,2268,2266],{"__ignoreMap":21},[12,2270,226],{},[16,2272,2275],{"className":2273,"code":2274,"language":115,"meta":21},[113],"直接返回\n",[23,2276,2274],{"__ignoreMap":21},[12,2278,2279],{},"而且 latch 一旦变成 0：",[16,2281,2284],{"className":2282,"code":2283,"language":115,"meta":21},[113],"以后一直保持“打开”\n",[23,2285,2283],{"__ignoreMap":21},[12,2287,2288],{},"不会重新关上。",[143,2290],{},[151,2292,2294],{"id":2293},"arrive_and_wait",[23,2295,2296],{},"arrive_and_wait()",[12,2298,2299],{},"如果当前线程：",[16,2301,2304],{"className":2302,"code":2303,"language":115,"meta":21},[113],"既是参与者\n\n又要等待其他参与者\n",[23,2305,2303],{"__ignoreMap":21},[12,2307,2308],{},"可以使用：",[16,2310,2312],{"className":18,"code":2311,"language":20,"meta":21,"style":21},"latch.arrive_and_wait();\n",[23,2313,2314],{"__ignoreMap":21},[26,2315,2316,2319,2321],{"class":28,"line":29},[26,2317,2318],{"class":36},"latch.",[26,2320,2293],{"class":73},[26,2322,214],{"class":36},[12,2324,1250],{},[16,2326,2329],{"className":2327,"code":2328,"language":115,"meta":21},[113],"我已经到达\n↓\n计数减一\n↓\n然后我也等待其他人到达\n",[23,2330,2328],{"__ignoreMap":21},[12,2332,2333],{},"也就是类似：",[16,2335,2337],{"className":18,"code":2336,"language":20,"meta":21,"style":21},"latch.count_down();\nlatch.wait();\n",[23,2338,2339,2347],{"__ignoreMap":21},[26,2340,2341,2343,2345],{"class":28,"line":29},[26,2342,2318],{"class":36},[26,2344,1817],{"class":73},[26,2346,214],{"class":36},[26,2348,2349,2351,2353],{"class":28,"line":43},[26,2350,2318],{"class":36},[26,2352,2067],{"class":73},[26,2354,214],{"class":36},[12,2356,2357,2358,2360],{},"不过 ",[23,2359,2296],{}," 表达意图更直接。",[143,2362],{},[151,2364,2366],{"id":2365},"latch-是一次性的","latch 是一次性的",[12,2368,2369],{},"这是 latch 最重要的特点：",[16,2371,2374],{"className":2372,"code":2373,"language":115,"meta":21},[113],"只能用一次\n",[23,2375,2373],{"__ignoreMap":21},[12,2377,180],{},[16,2379,2380],{"className":18,"code":1774,"language":20,"meta":21,"style":21},[23,2381,2382],{"__ignoreMap":21},[26,2383,2384,2386,2388,2390,2392,2394,2396],{"class":28,"line":29},[26,2385,74],{"class":73},[26,2387,374],{"class":36},[26,2389,48],{"class":73},[26,2391,1787],{"class":73},[26,2393,410],{"class":36},[26,2395,936],{"class":400},[26,2397,415],{"class":36},[12,2399,2400],{},"最终：",[16,2402,2405],{"className":2403,"code":2404,"language":115,"meta":21},[113],"3 → 2 → 1 → 0\n",[23,2406,2404],{"__ignoreMap":21},[12,2408,2409],{},"到 0 以后：",[16,2411,2414],{"className":2412,"code":2413,"language":115,"meta":21},[113],"不会重新回到 3\n",[23,2415,2413],{"__ignoreMap":21},[12,2417,2418],{},"所以 latch 特别适合：",[16,2420,2423],{"className":2421,"code":2422,"language":115,"meta":21},[113],"等待一批初始化任务完成\n\n等待几个线程启动就绪\n\n等待一次性并行任务全部结束\n",[23,2424,2422],{"__ignoreMap":21},[12,2426,2427],{},"而不适合：",[16,2429,2432],{"className":2430,"code":2431,"language":115,"meta":21},[113],"第一轮同步\n第二轮同步\n第三轮同步\n...\n",[23,2433,2431],{"__ignoreMap":21},[12,2435,2436],{},"这种场景应该用：",[16,2438,2440],{"className":18,"code":2439,"language":20,"meta":21,"style":21},"std::barrier\n",[23,2441,2442],{"__ignoreMap":21},[26,2443,2444,2446],{"class":28,"line":29},[26,2445,74],{"class":73},[26,2447,99],{"class":36},[143,2449],{},[151,2451,2453],{"id":2452},"latch-可以理解成一次性开门","latch 可以理解成“一次性开门”",[12,2455,180],{},[16,2457,2460],{"className":2458,"code":2459,"language":115,"meta":21},[113],"初始 latch(3)\n\n还差 3 人\n门关着\n\n还差 2 人\n门关着\n\n还差 1 人\n门关着\n\n最后 1 人到达\n计数变 0\n\n门打开\n\n以后永远保持打开\n",[23,2461,2459],{"__ignoreMap":21},[12,2463,120],{},[16,2465,2468],{"className":2466,"code":2467,"language":115,"meta":21},[113],"latch\n≈ 一次性会合点\n",[23,2469,2467],{"__ignoreMap":21},[143,2471],{},[146,2473,2475],{"id":2474},"barrier可重复阶段同步","barrier：可重复阶段同步",[151,2477,2479],{"id":2478},"barrier可重复的阶段同步","barrier：可重复的阶段同步",[12,2481,2482,2485],{},[23,2483,2484],{},"std::barrier"," 解决的是：",[170,2487,2488],{},[12,2489,2490],{},[175,2491,2492],{},"多个线程需要一轮一轮同步。",[12,2494,2495],{},"例如有三个线程：",[16,2497,2500],{"className":2498,"code":2499,"language":115,"meta":21},[113],"线程 A\n线程 B\n线程 C\n",[23,2501,2499],{"__ignoreMap":21},[12,2503,2504],{},"每个线程都要执行：",[16,2506,2509],{"className":2507,"code":2508,"language":115,"meta":21},[113],"第 1 阶段\n↓\n等待所有人完成\n\n第 2 阶段\n↓\n等待所有人完成\n\n第 3 阶段\n",[23,2510,2508],{"__ignoreMap":21},[12,2512,2513],{},"这时：",[16,2515,2516],{"className":18,"code":2439,"language":20,"meta":21,"style":21},[23,2517,2518],{"__ignoreMap":21},[26,2519,2520,2522],{"class":28,"line":29},[26,2521,74],{"class":73},[26,2523,99],{"class":36},[12,2525,2526],{},"非常合适。",[143,2528],{},[151,2530,2532],{"id":2531},"barrier-可以理解成每轮都要集合","barrier 可以理解成“每轮都要集合”",[12,2534,2535],{},"假设：",[16,2537,2539],{"className":18,"code":2538,"language":20,"meta":21,"style":21},"std::barrier sync_point(3);\n",[23,2540,2541],{"__ignoreMap":21},[26,2542,2543,2545,2547,2549,2552,2554,2556],{"class":28,"line":29},[26,2544,74],{"class":73},[26,2546,374],{"class":36},[26,2548,58],{"class":73},[26,2550,2551],{"class":73}," sync_point",[26,2553,410],{"class":36},[26,2555,936],{"class":400},[26,2557,415],{"class":36},[12,2559,268],{},[16,2561,2564],{"className":2562,"code":2563,"language":115,"meta":21},[113],"每一轮都要等 3 个参与者到达\n",[23,2565,2563],{"__ignoreMap":21},[12,2567,2568],{},"第一轮：",[16,2570,2573],{"className":2571,"code":2572,"language":115,"meta":21},[113],"A 到了\nB 到了\nC 到了\n↓\n3 人到齐\n↓\n全部放行进入下一轮\n",[23,2574,2572],{"__ignoreMap":21},[12,2576,2577],{},"然后 barrier 自动重新准备：",[16,2579,2582],{"className":2580,"code":2581,"language":115,"meta":21},[113],"下一轮继续等 3 人\n",[23,2583,2581],{"__ignoreMap":21},[12,2585,120],{},[16,2587,2590],{"className":2588,"code":2589,"language":115,"meta":21},[113],"latch\n→ 只集合一次\n\nbarrier\n→ 每一轮都重新集合\n",[23,2591,2589],{"__ignoreMap":21},[143,2593],{},[151,2595,2597],{"id":2596},"barrier-示例","barrier 示例",[16,2599,2601],{"className":18,"code":2600,"language":20,"meta":21,"style":21},"#include \u003Cbarrier>\n#include \u003Cprint>\n#include \u003Cthread>\n#include \u003Cvector>\n\nstd::barrier sync_point(3);\n\nvoid worker(int id)\n{\n    std::println(\"phase 1: {}\", id);\n\n    sync_point.arrive_and_wait();\n\n    std::println(\"phase 2: {}\", id);\n\n    sync_point.arrive_and_wait();\n\n    std::println(\"phase 3: {}\", id);\n}\n\nint main()\n{\n    std::vector\u003Cstd::thread> threads;\n\n    for (int i = 0; i \u003C 3; ++i)\n    {\n        threads.emplace_back(worker, i);\n    }\n\n    for (auto& thread : threads)\n    {\n        thread.join();\n    }\n}\n",[23,2602,2603,2610,2616,2622,2628,2632,2648,2652,2666,2670,2685,2689,2698,2702,2717,2721,2729,2733,2748,2752,2756,2764,2768,2784,2788,2814,2818,2826,2830,2834,2844,2848,2856,2860],{"__ignoreMap":21},[26,2604,2605,2607],{"class":28,"line":29},[26,2606,319],{"class":32},[26,2608,2609],{"class":322}," \u003Cbarrier>\n",[26,2611,2612,2614],{"class":28,"line":43},[26,2613,319],{"class":32},[26,2615,330],{"class":322},[26,2617,2618,2620],{"class":28,"line":53},[26,2619,319],{"class":32},[26,2621,344],{"class":322},[26,2623,2624,2626],{"class":28,"line":94},[26,2625,319],{"class":32},[26,2627,352],{"class":322},[26,2629,2630],{"class":28,"line":347},[26,2631,359],{"emptyLinePlaceholder":358},[26,2633,2634,2636,2638,2640,2642,2644,2646],{"class":28,"line":355},[26,2635,74],{"class":73},[26,2637,374],{"class":36},[26,2639,58],{"class":73},[26,2641,2551],{"class":73},[26,2643,410],{"class":36},[26,2645,936],{"class":400},[26,2647,415],{"class":36},[26,2649,2650],{"class":28,"line":362},[26,2651,359],{"emptyLinePlaceholder":358},[26,2653,2654,2656,2658,2660,2662,2664],{"class":28,"line":383},[26,2655,426],{"class":32},[26,2657,429],{"class":73},[26,2659,410],{"class":36},[26,2661,434],{"class":32},[26,2663,438],{"class":437},[26,2665,441],{"class":36},[26,2667,2668],{"class":28,"line":388},[26,2669,447],{"class":36},[26,2671,2672,2674,2676,2678,2680,2683],{"class":28,"line":418},[26,2673,468],{"class":73},[26,2675,374],{"class":36},[26,2677,473],{"class":73},[26,2679,410],{"class":36},[26,2681,2682],{"class":322},"\"phase 1: {}\"",[26,2684,481],{"class":36},[26,2686,2687],{"class":28,"line":423},[26,2688,359],{"emptyLinePlaceholder":358},[26,2690,2691,2694,2696],{"class":28,"line":444},[26,2692,2693],{"class":36},"    sync_point.",[26,2695,2293],{"class":73},[26,2697,214],{"class":36},[26,2699,2700],{"class":28,"line":450},[26,2701,359],{"emptyLinePlaceholder":358},[26,2703,2704,2706,2708,2710,2712,2715],{"class":28,"line":460},[26,2705,468],{"class":73},[26,2707,374],{"class":36},[26,2709,473],{"class":73},[26,2711,410],{"class":36},[26,2713,2714],{"class":322},"\"phase 2: {}\"",[26,2716,481],{"class":36},[26,2718,2719],{"class":28,"line":465},[26,2720,359],{"emptyLinePlaceholder":358},[26,2722,2723,2725,2727],{"class":28,"line":484},[26,2724,2693],{"class":36},[26,2726,2293],{"class":73},[26,2728,214],{"class":36},[26,2730,2731],{"class":28,"line":489},[26,2732,359],{"emptyLinePlaceholder":358},[26,2734,2735,2737,2739,2741,2743,2746],{"class":28,"line":514},[26,2736,468],{"class":73},[26,2738,374],{"class":36},[26,2740,473],{"class":73},[26,2742,410],{"class":36},[26,2744,2745],{"class":322},"\"phase 3: {}\"",[26,2747,481],{"class":36},[26,2749,2750],{"class":28,"line":519},[26,2751,552],{"class":36},[26,2753,2754],{"class":28,"line":535},[26,2755,359],{"emptyLinePlaceholder":358},[26,2757,2758,2760,2762],{"class":28,"line":540},[26,2759,434],{"class":32},[26,2761,565],{"class":73},[26,2763,568],{"class":36},[26,2765,2766],{"class":28,"line":549},[26,2767,447],{"class":36},[26,2769,2770,2772,2774,2776,2778,2780,2782],{"class":28,"line":555},[26,2771,468],{"class":73},[26,2773,581],{"class":36},[26,2775,33],{"class":32},[26,2777,74],{"class":73},[26,2779,588],{"class":36},[26,2781,591],{"class":32},[26,2783,594],{"class":36},[26,2785,2786],{"class":28,"line":560},[26,2787,359],{"emptyLinePlaceholder":358},[26,2789,2790,2792,2794,2796,2798,2800,2802,2804,2806,2808,2810,2812],{"class":28,"line":571},[26,2791,605],{"class":32},[26,2793,608],{"class":36},[26,2795,434],{"class":32},[26,2797,613],{"class":36},[26,2799,616],{"class":32},[26,2801,619],{"class":400},[26,2803,622],{"class":36},[26,2805,33],{"class":32},[26,2807,2034],{"class":400},[26,2809,630],{"class":36},[26,2811,633],{"class":32},[26,2813,636],{"class":36},[26,2815,2816],{"class":28,"line":576},[26,2817,642],{"class":36},[26,2819,2820,2822,2824],{"class":28,"line":597},[26,2821,648],{"class":36},[26,2823,651],{"class":73},[26,2825,654],{"class":36},[26,2827,2828],{"class":28,"line":602},[26,2829,660],{"class":36},[26,2831,2832],{"class":28,"line":639},[26,2833,359],{"emptyLinePlaceholder":358},[26,2835,2836,2838,2840,2842],{"class":28,"line":645},[26,2837,605],{"class":32},[26,2839,608],{"class":36},[26,2841,675],{"class":32},[26,2843,678],{"class":36},[26,2845,2846],{"class":28,"line":657},[26,2847,642],{"class":36},[26,2849,2850,2852,2854],{"class":28,"line":663},[26,2851,689],{"class":36},[26,2853,692],{"class":73},[26,2855,214],{"class":36},[26,2857,2858],{"class":28,"line":668},[26,2859,660],{"class":36},[26,2861,2862],{"class":28,"line":681},[26,2863,552],{"class":36},[12,2865,707],{},[16,2867,2870],{"className":2868,"code":2869,"language":115,"meta":21},[113],"phase 1: 2\nphase 1: 0\nphase 1: 1\n\nphase 2: 1\nphase 2: 2\nphase 2: 0\n\nphase 3: 0\nphase 3: 2\nphase 3: 1\n",[23,2871,2869],{"__ignoreMap":21},[12,2873,2874],{},"每个阶段内部：",[16,2876,2879],{"className":2877,"code":2878,"language":115,"meta":21},[113],"谁先打印\n",[23,2880,2878],{"__ignoreMap":21},[12,2882,2883],{},"不确定。",[12,2885,2886],{},"但是一定满足：",[16,2888,2891],{"className":2889,"code":2890,"language":115,"meta":21},[113],"所有 phase 1 都完成\n↓\n才可能出现 phase 2\n\n所有 phase 2 都完成\n↓\n才可能出现 phase 3\n",[23,2892,2890],{"__ignoreMap":21},[12,2894,2895],{},"所以不会出现：",[16,2897,2900],{"className":2898,"code":2899,"language":115,"meta":21},[113],"线程 A 已经进入 phase 2\n\n但线程 B 连 phase 1 的 barrier 都还没到\n",[23,2901,2899],{"__ignoreMap":21},[143,2903],{},[151,2905,2907],{"id":2906},"arrive_and_wait-1",[23,2908,2296],{},[12,2910,2911],{},"barrier 最常见的操作：",[16,2913,2915],{"className":18,"code":2914,"language":20,"meta":21,"style":21},"sync_point.arrive_and_wait();\n",[23,2916,2917],{"__ignoreMap":21},[26,2918,2919,2922,2924],{"class":28,"line":29},[26,2920,2921],{"class":36},"sync_point.",[26,2923,2293],{"class":73},[26,2925,214],{"class":36},[12,2927,268],{},[16,2929,2932],{"className":2930,"code":2931,"language":115,"meta":21},[113],"我已经完成这一阶段\n↓\n记录一次到达\n↓\n然后等其他参与者\n",[23,2933,2931],{"__ignoreMap":21},[12,2935,2936],{},"当本阶段所有参与者都到达以后：",[16,2938,2941],{"className":2939,"code":2940,"language":115,"meta":21},[113],"所有等待线程一起进入下一阶段\n",[23,2942,2940],{"__ignoreMap":21},[12,2944,120],{},[16,2946,2948],{"className":18,"code":2947,"language":20,"meta":21,"style":21},"arrive_and_wait();\n",[23,2949,2950],{"__ignoreMap":21},[26,2951,2952,2954],{"class":28,"line":29},[26,2953,2293],{"class":73},[26,2955,214],{"class":36},[12,2957,2958],{},"非常符合：",[16,2960,2963],{"className":2961,"code":2962,"language":115,"meta":21},[113],"“这一轮我做完了，现在等大家。”\n",[23,2964,2962],{"__ignoreMap":21},[12,2966,2967],{},"这种语义。",[143,2969],{},[151,2971,2973],{"id":2972},"barrier-会自动进入下一轮","barrier 会自动进入下一轮",[12,2975,2976],{},"这是它和 latch 最大的不同。",[12,2978,2979],{},"latch：",[16,2981,2984],{"className":2982,"code":2983,"language":115,"meta":21},[113],"计数归零\n↓\n永久打开\n↓\n结束\n",[23,2985,2983],{"__ignoreMap":21},[12,2987,2988],{},"barrier：",[16,2990,2993],{"className":2991,"code":2992,"language":115,"meta":21},[113],"本轮所有人到达\n↓\n本轮完成\n↓\n自动开始下一轮\n↓\n重新等待参与者\n",[23,2994,2992],{"__ignoreMap":21},[12,2996,120],{},[16,2998,3001],{"className":2999,"code":3000,"language":115,"meta":21},[113],"latch\n→ 一次性同步\n\nbarrier\n→ 循环同步\n",[23,3002,3000],{"__ignoreMap":21},[143,3004],{},[151,3006,3008],{"id":3007},"completion-function","completion function",[12,3010,3011,3013],{},[23,3012,2484],{}," 还可以设置：",[170,3015,3016],{},[12,3017,3018],{},[175,3019,3020],{},"阶段完成函数（completion function）",[12,3022,3023],{},"它会在：",[16,3025,3028],{"className":3026,"code":3027,"language":115,"meta":21},[113],"本轮所有参与者都到达\n",[23,3029,3027],{"__ignoreMap":21},[12,3031,3032],{},"以后执行一次。",[12,3034,3035],{},"概念上：",[16,3037,3040],{"className":3038,"code":3039,"language":115,"meta":21},[113],"所有线程完成第 N 阶段\n        ↓\ncompletion function\n        ↓\n进入第 N+1 阶段\n",[23,3041,3039],{"__ignoreMap":21},[12,3043,3044],{},"这适合：",[16,3046,3049],{"className":3047,"code":3048,"language":115,"meta":21},[113],"所有线程完成本轮计算\n↓\n统一更新一次共享状态\n↓\n所有线程开始下一轮\n",[23,3050,3048],{"__ignoreMap":21},[12,3052,3053],{},"例如并行算法可能需要：",[16,3055,3058],{"className":3056,"code":3057,"language":115,"meta":21},[113],"第 1 轮：\n每个线程算自己那部分\n\n所有人到 barrier\n\ncompletion：\n交换 \u002F 汇总本轮结果\n\n第 2 轮：\n基于新结果继续计算\n",[23,3059,3057],{"__ignoreMap":21},[143,3061],{},[151,3063,3065],{"id":3064},"completion-function-不要做太重的事情","completion function 不要做太重的事情",[12,3067,3068],{},"因为：",[16,3070,3073],{"className":3071,"code":3072,"language":115,"meta":21},[113],"所有参与者都在等这个阶段真正结束\n",[23,3074,3072],{"__ignoreMap":21},[12,3076,3077],{},"所以 completion function 如果：",[16,3079,3082],{"className":3080,"code":3081,"language":115,"meta":21},[113],"执行很慢\n\n做长时间 IO\n\nsleep\n\n等待其他锁\n\n执行复杂阻塞操作\n",[23,3083,3081],{"__ignoreMap":21},[12,3085,3086],{},"那么所有参与者都会一起被拖住。",[12,3088,3089],{},"所以 completion function 更适合：",[16,3091,3094],{"className":3092,"code":3093,"language":115,"meta":21},[113],"很短的状态更新\n\n交换阶段数据\n\n维护轮次\n\n轻量汇总\n",[23,3095,3093],{"__ignoreMap":21},[143,3097],{},[151,3099,3101],{"id":3100},"arrive_and_drop",[23,3102,3103],{},"arrive_and_drop()",[12,3105,3106],{},"假设 barrier 初始有：",[16,3108,3111],{"className":3109,"code":3110,"language":115,"meta":21},[113],"3 个参与者\n",[23,3112,3110],{"__ignoreMap":21},[12,3114,3115],{},"但某个线程执行完当前阶段以后：",[170,3117,3118],{},[12,3119,3120],{},"后面几轮不再参加了。",[12,3122,3123],{},"这时不能直接：",[16,3125,3128],{"className":3126,"code":3127,"language":115,"meta":21},[113],"退出线程\n",[23,3129,3127],{"__ignoreMap":21},[12,3131,3132],{},"因为 barrier 还以为：",[16,3134,3137],{"className":3135,"code":3136,"language":115,"meta":21},[113],"下一轮仍然要等 3 人\n",[23,3138,3136],{"__ignoreMap":21},[12,3140,3141],{},"但实际上以后只有：",[16,3143,3146],{"className":3144,"code":3145,"language":115,"meta":21},[113],"2 人\n",[23,3147,3145],{"__ignoreMap":21},[12,3149,3150],{},"于是其他两个线程永远等不到第三个。",[12,3152,3153],{},"所以需要：",[16,3155,3157],{"className":18,"code":3156,"language":20,"meta":21,"style":21},"barrier.arrive_and_drop();\n",[23,3158,3159],{"__ignoreMap":21},[26,3160,3161,3164,3166],{"class":28,"line":29},[26,3162,3163],{"class":36},"barrier.",[26,3165,3100],{"class":73},[26,3167,214],{"class":36},[12,3169,268],{},[16,3171,3174],{"className":3172,"code":3173,"language":115,"meta":21},[113],"我完成了本轮到达\n\n并且：\n\n以后每一轮都不用再等我\n",[23,3175,3173],{"__ignoreMap":21},[12,3177,3178],{},"也就是把未来参与者数量永久减掉。",[143,3180],{},[146,3182,3183],{"id":3183},"选择与对比",[151,3185,3187],{"id":3186},"latch-和-barrier-最核心的区别","latch 和 barrier 最核心的区别",[12,3189,3190],{},"可以直接这样记：",[16,3192,3195],{"className":3193,"code":3194,"language":115,"meta":21},[113],"latch\n→ 一次性的\n\nbarrier\n→ 可重复的\n",[23,3196,3194],{"__ignoreMap":21},[12,3198,180],{},[3200,3201,48],"h4",{"id":48},[16,3203,3206],{"className":3204,"code":3205,"language":115,"meta":21},[113],"等 4 个模块初始化完成\n↓\n程序正式启动\n",[23,3207,3205],{"__ignoreMap":21},[12,3209,3210],{},"初始化只发生一次。",[12,3212,120],{},[16,3214,3216],{"className":18,"code":3215,"language":20,"meta":21,"style":21},"std::latch\n",[23,3217,3218],{"__ignoreMap":21},[26,3219,3220,3222],{"class":28,"line":29},[26,3221,74],{"class":73},[26,3223,91],{"class":36},[12,3225,3226],{},"很合适。",[3200,3228,58],{"id":58},[16,3230,3233],{"className":3231,"code":3232,"language":115,"meta":21},[113],"4 个线程一起做第 1 轮\n↓\n集合\n\n一起做第 2 轮\n↓\n集合\n\n一起做第 3 轮\n↓\n集合\n",[23,3234,3232],{"__ignoreMap":21},[12,3236,3237],{},"每一轮都要同步。",[12,3239,120],{},[16,3241,3242],{"className":18,"code":2439,"language":20,"meta":21,"style":21},[23,3243,3244],{"__ignoreMap":21},[26,3245,3246,3248],{"class":28,"line":29},[26,3247,74],{"class":73},[26,3249,99],{"class":36},[12,3251,3252],{},"更合适。",[143,3254],{},[151,3256,3258],{"id":3257},"semaphorelatchbarrier-怎么选","semaphore、latch、barrier 怎么选",[12,3260,3261],{},"可以直接看这张表：",[3263,3264,3265,3278],"table",{},[3266,3267,3268],"thead",{},[3269,3270,3271,3275],"tr",{},[3272,3273,3274],"th",{},"需求",[3272,3276,3277],{},"推荐工具",[3279,3280,3281,3291,3300,3309,3318,3328],"tbody",{},[3269,3282,3283,3287],{},[3284,3285,3286],"td",{},"最多允许 N 个线程同时获得资源",[3284,3288,3289],{},[23,3290,160],{},[3269,3292,3293,3296],{},[3284,3294,3295],{},"一个简单的 0 \u002F 1 许可或线程间信号",[3284,3297,3298],{},[23,3299,1233],{},[3269,3301,3302,3305],{},[3284,3303,3304],{},"等 N 个参与者一次性全部完成",[3284,3306,3307],{},[23,3308,1761],{},[3269,3310,3311,3314],{},[3284,3312,3313],{},"多个线程每轮都要同步",[3284,3315,3316],{},[23,3317,2484],{},[3269,3319,3320,3323],{},[3284,3321,3322],{},"保护共享对象一致性",[3284,3324,3325],{},[23,3326,3327],{},"std::mutex",[3269,3329,3330,3333],{},[3284,3331,3332],{},"等复杂共享条件成立",[3284,3334,3335],{},[23,3336,3337],{},"std::condition_variable",[143,3339],{},[151,3341,3343],{"id":3342},"和-mutex-的区别","和 mutex 的区别",[12,3345,3346,3348],{},[23,3347,105],{}," 关注的是：",[16,3350,3353],{"className":3351,"code":3352,"language":115,"meta":21},[113],"谁能进入临界区\n",[23,3354,3352],{"__ignoreMap":21},[12,3356,180],{},[16,3358,3360],{"className":18,"code":3359,"language":20,"meta":21,"style":21},"std::scoped_lock lock(mutex);\n",[23,3361,3362],{"__ignoreMap":21},[26,3363,3364,3366,3368,3371,3374,3376,3378],{"class":28,"line":29},[26,3365,74],{"class":73},[26,3367,374],{"class":36},[26,3369,3370],{"class":73},"scoped_lock",[26,3372,3373],{"class":73}," lock",[26,3375,410],{"class":36},[26,3377,105],{"class":73},[26,3379,415],{"class":36},[12,3381,3382],{},"表达：",[16,3384,3387],{"className":3385,"code":3386,"language":115,"meta":21},[113],"这段共享数据同时只允许一个线程操作\n",[23,3388,3386],{"__ignoreMap":21},[12,3390,3391],{},"而 semaphore 关注：",[16,3393,3396],{"className":3394,"code":3395,"language":115,"meta":21},[113],"还有多少许可\n",[23,3397,3395],{"__ignoreMap":21},[12,3399,3400],{},"latch 关注：",[16,3402,3405],{"className":3403,"code":3404,"language":115,"meta":21},[113],"还有多少参与者没完成\n",[23,3406,3404],{"__ignoreMap":21},[12,3408,3409],{},"barrier 关注：",[16,3411,3414],{"className":3412,"code":3413,"language":115,"meta":21},[113],"这一轮所有参与者到齐了吗\n",[23,3415,3413],{"__ignoreMap":21},[12,3417,3418],{},"所以这些工具：",[16,3420,3423],{"className":3421,"code":3422,"language":115,"meta":21},[113],"不是 mutex 的不同写法\n",[23,3424,3422],{"__ignoreMap":21},[12,3426,3427],{},"而是：",[16,3429,3432],{"className":3430,"code":3431,"language":115,"meta":21},[113],"解决不同同步模式\n",[23,3433,3431],{"__ignoreMap":21},[143,3435],{},[151,3437,3439],{"id":3438},"和-condition_variable-的关系","和 condition_variable 的关系",[12,3441,3442],{},"理论上很多同步器都可以自己手搓。",[12,3444,3445],{},"例如 latch 可以大概用：",[16,3447,3450],{"className":3448,"code":3449,"language":115,"meta":21},[113],"counter\n\nmutex\n\ncondition_variable\n",[23,3451,3449],{"__ignoreMap":21},[12,3453,3454],{},"实现：",[16,3456,3459],{"className":3457,"code":3458,"language":115,"meta":21},[113],"counter 每完成一个任务减 1\n\ncounter == 0\n↓\nnotify_all()\n",[23,3460,3458],{"__ignoreMap":21},[12,3462,3463],{},"barrier 也可以自己维护：",[16,3465,3468],{"className":3466,"code":3467,"language":115,"meta":21},[113],"当前轮次\n参与者数量\n已到达数量\ncondition_variable\n",[23,3469,3467],{"__ignoreMap":21},[12,3471,3472],{},"实现。",[12,3474,3475],{},"但这很容易产生：",[16,3477,3480],{"className":3478,"code":3479,"language":115,"meta":21},[113],"计数错误\n\n边界条件错误\n\n通知丢失\n\n轮次状态错误\n\n异常退出后人数不一致\n",[23,3481,3479],{"__ignoreMap":21},[12,3483,120],{},[16,3485,3488],{"className":3486,"code":3487,"language":115,"meta":21},[113],"condition_variable\n→ 通用零件\n\nsemaphore \u002F latch \u002F barrier\n→ 已经封装好的常见同步模式\n",[23,3489,3487],{"__ignoreMap":21},[12,3491,3492],{},"如果标准库已经有你想表达的模型：",[16,3494,3497],{"className":3495,"code":3496,"language":115,"meta":21},[113],"优先使用标准抽象\n",[23,3498,3496],{"__ignoreMap":21},[12,3500,3501],{},"通常会让代码：",[16,3503,3506],{"className":3504,"code":3505,"language":115,"meta":21},[113],"更短\n\n更清楚\n\n更不容易写错\n\n更容易让别人看懂\n",[23,3507,3505],{"__ignoreMap":21},[143,3509],{},[151,3511,3513],{"id":3512},"semaphore-的典型场景","semaphore 的典型场景",[12,3515,3516,3518],{},[23,3517,395],{}," 常见于：",[16,3520,3523],{"className":3521,"code":3522,"language":115,"meta":21},[113],"限制同时下载任务数量\n\n限制数据库连接数\n\n限制 GPU \u002F 加速器任务并发数\n\n资源池可用对象数量\n\n限制同时进行的网络请求\n\n控制同时执行的重任务数量\n",[23,3524,3522],{"__ignoreMap":21},[12,3526,180],{},[16,3528,3531],{"className":3529,"code":3530,"language":115,"meta":21},[113],"线程可以有 100 个\n\n但数据库连接池只有 10 个连接\n\n→ semaphore 初始许可 = 10\n",[23,3532,3530],{"__ignoreMap":21},[12,3534,3535],{},"这就很自然。",[143,3537],{},[151,3539,3541],{"id":3540},"latch-的典型场景","latch 的典型场景",[12,3543,3544],{},"latch 常见于：",[16,3546,3549],{"className":3547,"code":3548,"language":115,"meta":21},[113],"多个模块并行初始化\n\n主线程等待所有初始化结束\n\n多个并行任务全部完成后统一继续\n\n启动多个 worker，等待全部 ready\n",[23,3550,3548],{"__ignoreMap":21},[12,3552,3553],{},"关键词是：",[16,3555,3558],{"className":3556,"code":3557,"language":115,"meta":21},[113],"一次性\n",[23,3559,3557],{"__ignoreMap":21},[143,3561],{},[151,3563,3565],{"id":3564},"barrier-的典型场景","barrier 的典型场景",[12,3567,3568],{},"barrier 常见于：",[16,3570,3573],{"className":3571,"code":3572,"language":115,"meta":21},[113],"并行数值计算\n\n迭代算法\n\n分块处理\n\n多线程仿真\n\n每一轮都依赖上一轮完整结果\n",[23,3574,3572],{"__ignoreMap":21},[12,3576,3553],{},[16,3578,3581],{"className":3579,"code":3580,"language":115,"meta":21},[113],"一轮一轮同步\n",[23,3582,3580],{"__ignoreMap":21},[143,3584],{},[146,3586,3587],{"id":3587},"常见错误",[151,3589,3591],{"id":3590},"错误把-semaphore-当-mutex","错误：把 semaphore 当 mutex",[12,3593,3594],{},"错误理解：",[16,3596,3599],{"className":3597,"code":3598,"language":115,"meta":21},[113],"用了 semaphore\n→ 共享 vector 自动线程安全\n",[23,3600,3598],{"__ignoreMap":21},[12,3602,3603],{},"不对。",[12,3605,3606],{},"semaphore 只控制：",[16,3608,3611],{"className":3609,"code":3610,"language":115,"meta":21},[113],"许可数量\n",[23,3612,3610],{"__ignoreMap":21},[12,3614,3615],{},"共享对象的一致性仍然可能需要：",[16,3617,3618],{"className":18,"code":1450,"language":20,"meta":21,"style":21},[23,3619,3620],{"__ignoreMap":21},[26,3621,3622,3624],{"class":28,"line":29},[26,3623,74],{"class":73},[26,3625,1459],{"class":36},[143,3627],{},[151,3629,3631],{"id":3630},"错误acquire-以后忘记-release","错误：acquire 以后忘记 release",[12,3633,180],{},[16,3635,3637],{"className":18,"code":3636,"language":20,"meta":21,"style":21},"semaphore.acquire();\n\nif (error)\n{\n    return; \u002F\u002F 忘了 release\n}\n",[23,3638,3639,3647,3651,3658,3662,3673],{"__ignoreMap":21},[26,3640,3641,3643,3645],{"class":28,"line":29},[26,3642,208],{"class":36},[26,3644,211],{"class":73},[26,3646,214],{"class":36},[26,3648,3649],{"class":28,"line":43},[26,3650,359],{"emptyLinePlaceholder":358},[26,3652,3653,3655],{"class":28,"line":53},[26,3654,1091],{"class":32},[26,3656,3657],{"class":36}," (error)\n",[26,3659,3660],{"class":28,"line":94},[26,3661,447],{"class":36},[26,3663,3664,3667,3670],{"class":28,"line":347},[26,3665,3666],{"class":32},"    return",[26,3668,3669],{"class":36},";",[26,3671,3672],{"class":1108}," \u002F\u002F 忘了 release\n",[26,3674,3675],{"class":28,"line":355},[26,3676,552],{"class":36},[12,3678,3679],{},"这样会永久损失一个许可。",[143,3681],{},[151,3683,3685],{"id":3684},"错误认为-binary-semaphore-有-mutex-的所有权规则","错误：认为 binary semaphore 有 mutex 的所有权规则",[12,3687,3688],{},"binary semaphore 虽然只有：",[16,3690,3693],{"className":3691,"code":3692,"language":115,"meta":21},[113],"0 \u002F 1\n",[23,3694,3692],{"__ignoreMap":21},[12,3696,3697],{},"但它仍然：",[16,3699,3702],{"className":3700,"code":3701,"language":115,"meta":21},[113],"不是 mutex\n",[23,3703,3701],{"__ignoreMap":21},[12,3705,3706],{},"许可可以由不同线程 acquire \u002F release。",[143,3708],{},[151,3710,3712],{"id":3711},"错误把-latch-当成可以重置的工具","错误：把 latch 当成可以重置的工具",[12,3714,3715,1467],{},[23,3716,1761],{},[16,3718,3721],{"className":3719,"code":3720,"language":115,"meta":21},[113],"只能归零一次\n",[23,3722,3720],{"__ignoreMap":21},[12,3724,3725],{},"归零以后不会：",[16,3727,3730],{"className":3728,"code":3729,"language":115,"meta":21},[113],"重新恢复初始计数\n",[23,3731,3729],{"__ignoreMap":21},[12,3733,3734],{},"需要循环同步时用：",[16,3736,3737],{"className":18,"code":2439,"language":20,"meta":21,"style":21},[23,3738,3739],{"__ignoreMap":21},[26,3740,3741,3743],{"class":28,"line":29},[26,3742,74],{"class":73},[26,3744,99],{"class":36},[143,3746],{},[151,3748,3750],{"id":3749},"错误barrier-的参与人数写错","错误：barrier 的参与人数写错",[12,3752,180],{},[16,3754,3756],{"className":18,"code":3755,"language":20,"meta":21,"style":21},"std::barrier barrier(4);\n",[23,3757,3758],{"__ignoreMap":21},[26,3759,3760,3762,3764,3766,3769,3771,3773],{"class":28,"line":29},[26,3761,74],{"class":73},[26,3763,374],{"class":36},[26,3765,58],{"class":73},[26,3767,3768],{"class":73}," barrier",[26,3770,410],{"class":36},[26,3772,1572],{"class":400},[26,3774,415],{"class":36},[12,3776,3777],{},"但实际上只有：",[16,3779,3782],{"className":3780,"code":3781,"language":115,"meta":21},[113],"3 个线程\n",[23,3783,3781],{"__ignoreMap":21},[12,3785,3786],{},"会调用：",[16,3788,3789],{"className":18,"code":2947,"language":20,"meta":21,"style":21},[23,3790,3791],{"__ignoreMap":21},[26,3792,3793,3795],{"class":28,"line":29},[26,3794,2293],{"class":73},[26,3796,214],{"class":36},[12,3798,226],{},[16,3800,3803],{"className":3801,"code":3802,"language":115,"meta":21},[113],"永远差第 4 个参与者\n",[23,3804,3802],{"__ignoreMap":21},[12,3806,3807],{},"所有线程都可能永久卡住。",[143,3809],{},[151,3811,3813,3814],{"id":3812},"错误线程退出了却没-arrive_and_drop","错误：线程退出了，却没 ",[23,3815,3103],{},[12,3817,3818],{},"如果某个 barrier 参与者：",[16,3820,3823],{"className":3821,"code":3822,"language":115,"meta":21},[113],"以后不再参加后续轮次\n",[23,3824,3822],{"__ignoreMap":21},[12,3826,3827],{},"却直接退出，那么 barrier 仍然会：",[16,3829,3832],{"className":3830,"code":3831,"language":115,"meta":21},[113],"在后续每一轮等它\n",[23,3833,3831],{"__ignoreMap":21},[12,3835,3836],{},"应该：",[16,3838,3840],{"className":18,"code":3839,"language":20,"meta":21,"style":21},"arrive_and_drop();\n",[23,3841,3842],{"__ignoreMap":21},[26,3843,3844,3846],{"class":28,"line":29},[26,3845,3100],{"class":73},[26,3847,214],{"class":36},[143,3849],{},[151,3851,3853],{"id":3852},"错误completion-function-太慢","错误：completion function 太慢",[12,3855,3856],{},"completion function 执行期间：",[16,3858,3861],{"className":3859,"code":3860,"language":115,"meta":21},[113],"所有参与者都在等阶段完成\n",[23,3862,3860],{"__ignoreMap":21},[12,3864,3865],{},"所以里面不适合：",[16,3867,3870],{"className":3868,"code":3869,"language":115,"meta":21},[113],"长时间 IO\n\nsleep\n\n复杂阻塞\n\n重计算\n\n危险的锁嵌套\n",[23,3871,3869],{"__ignoreMap":21},[143,3873],{},[146,3875,3876],{"id":3876},"最后总结",[12,3878,3879],{},"这三个 C++20 同步工具可以这样记：",[16,3881,3884],{"className":3882,"code":3883,"language":115,"meta":21},[113],"semaphore\n→ 有几张通行证\n\nlatch\n→ 一次性等大家到齐\n\nbarrier\n→ 每一轮都等大家到齐\n",[23,3885,3883],{"__ignoreMap":21},[12,3887,3888],{},"更具体一点：",[16,3890,3893],{"className":3891,"code":3892,"language":115,"meta":21},[113],"std::counting_semaphore\n→ 允许同时存在多个许可\n\nstd::binary_semaphore\n→ 只有 0 \u002F 1 个许可\n\nstd::latch\n→ 一次性倒计时，归零后永久打开\n\nstd::barrier\n→ 每轮所有参与者到达后，自动开始下一轮\n",[23,3894,3892],{"__ignoreMap":21},[12,3896,3897],{},"它们和 mutex 的关系：",[16,3899,3902],{"className":3900,"code":3901,"language":115,"meta":21},[113],"mutex\n→ 保护共享状态\n\nsemaphore \u002F latch \u002F barrier\n→ 表达更高层的同步模式\n",[23,3903,3901],{"__ignoreMap":21},[12,3905,3906],{},"如果能用标准同步原语直接表达你的需求：",[170,3908,3909],{},[12,3910,3911],{},[175,3912,3913,3914,3917],{},"优先使用标准工具，而不是手写 ",[23,3915,3916],{},"mutex + condition_variable + counter","。",[12,3919,3920],{},"最后可以用一句话彻底区分：",[16,3922,3925],{"className":3923,"code":3924,"language":115,"meta":21},[113],"mutex\n→ “谁能进？”\n\nsemaphore\n→ “还能进几个？”\n\nlatch\n→ “这一次人到齐了吗？”\n\nbarrier\n→ “这一轮人到齐了吗？”\n",[23,3926,3924],{"__ignoreMap":21},[3928,3929,3930],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":21,"searchDepth":43,"depth":43,"links":3932},[3933,3947,3957,3967,3976,3986],{"id":148,"depth":43,"text":149,"children":3934},[3935,3936,3937,3938,3939,3940,3941,3942,3943,3944,3945,3946],{"id":153,"depth":53,"text":154},{"id":157,"depth":53,"text":160},{"id":301,"depth":53,"text":302},{"id":811,"depth":53,"text":812},{"id":907,"depth":53,"text":907},{"id":1066,"depth":53,"text":1069},{"id":1161,"depth":53,"text":1162},{"id":1230,"depth":53,"text":1233},{"id":1350,"depth":53,"text":1351},{"id":1443,"depth":53,"text":1444},{"id":1510,"depth":53,"text":1511},{"id":1635,"depth":53,"text":1636},{"id":1751,"depth":43,"text":1752,"children":3948},[3949,3950,3951,3952,3953,3954,3955,3956],{"id":1755,"depth":53,"text":1756},{"id":1848,"depth":53,"text":1849},{"id":1872,"depth":53,"text":1873},{"id":1817,"depth":53,"text":2178},{"id":2067,"depth":53,"text":2225},{"id":2293,"depth":53,"text":2296},{"id":2365,"depth":53,"text":2366},{"id":2452,"depth":53,"text":2453},{"id":2474,"depth":43,"text":2475,"children":3958},[3959,3960,3961,3962,3963,3964,3965,3966],{"id":2478,"depth":53,"text":2479},{"id":2531,"depth":53,"text":2532},{"id":2596,"depth":53,"text":2597},{"id":2906,"depth":53,"text":2296},{"id":2972,"depth":53,"text":2973},{"id":3007,"depth":53,"text":3008},{"id":3064,"depth":53,"text":3065},{"id":3100,"depth":53,"text":3103},{"id":3183,"depth":43,"text":3183,"children":3968},[3969,3970,3971,3972,3973,3974,3975],{"id":3186,"depth":53,"text":3187},{"id":3257,"depth":53,"text":3258},{"id":3342,"depth":53,"text":3343},{"id":3438,"depth":53,"text":3439},{"id":3512,"depth":53,"text":3513},{"id":3540,"depth":53,"text":3541},{"id":3564,"depth":53,"text":3565},{"id":3587,"depth":43,"text":3587,"children":3977},[3978,3979,3980,3981,3982,3983,3985],{"id":3590,"depth":53,"text":3591},{"id":3630,"depth":53,"text":3631},{"id":3684,"depth":53,"text":3685},{"id":3711,"depth":53,"text":3712},{"id":3749,"depth":53,"text":3750},{"id":3812,"depth":53,"text":3984},"错误：线程退出了，却没 arrive_and_drop()",{"id":3852,"depth":53,"text":3853},{"id":3876,"depth":43,"text":3876},"2000-1900-1700","2023-10-05","2023-10-05-cplusplus-jiao-xue","\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue","Cplusplus教学","md",false,{},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1900-1700-semaphore-latch-barrier",{"title":5,"description":14},"wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1900-1700-semaphore-latch-barrier","7Z5Yxz36b4GHbYjLNtXQjTrLLGqb_8vJx5s6V7koWKI",[4000,4007,4013,4019,4025,4031,4037,4043,4049,4055,4061,4067,4073,4079,4085,4091,4097,4103,4109,4115,4121,4127,4133,4139,4145,4151,4157,4163,4169,4175,4181,4187,4193,4199,4205,4211,4217,4223,4229,4235,4241,4247,4252,4258,4264,4270,4276,4282,4288,4294,4300,4306,4312,4318,4324,4330,4336,4342,4348,4354,4360,4366,4372,4378,4384,4390,4396,4402,4404,4410,4416,4422,4428,4434,4440,4446,4452,4458,4464,4470,4476,4482,4488,4494,4500,4506,4512,4518,4524,4530,4536,4542],{"path":4001,"stem":4002,"title":4003,"authors":4004,"date":3988,"chapterOrder":4005,"chapterDepth":4006,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F0100-c-kai-fa-huan-jing-da-jian-yu-ce-shi","wiki\u002F2023-10-05-Cplusplus教学\u002F0100-C++开发环境搭建与测试","C++开发环境搭建与测试",[7],"0100",0,{"path":4008,"stem":4009,"title":4010,"authors":4011,"date":3988,"chapterOrder":4012,"chapterDepth":4006,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F0200-c-ji-chu-chu-shi","wiki\u002F2023-10-05-Cplusplus教学\u002F0200-C++基础初识","C++基础初识",[7],"0200",{"path":4014,"stem":4015,"title":4016,"authors":4017,"date":3988,"chapterOrder":4018,"chapterDepth":4006,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F0300-shu-ju-lei-xing-yu-shu-ju-cun-fang","wiki\u002F2023-10-05-Cplusplus教学\u002F0300-数据类型与数据存放","数据类型与数据存放",[7],"0300",{"path":4020,"stem":4021,"title":4022,"authors":4023,"date":3988,"chapterOrder":4024,"chapterDepth":4006,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F0400-shu-ru-shu-chu","wiki\u002F2023-10-05-Cplusplus教学\u002F0400-输入输出","输入输出",[7],"0400",{"path":4026,"stem":4027,"title":4028,"authors":4029,"date":3988,"chapterOrder":4030,"chapterDepth":4006,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F0500-yun-suan-fu","wiki\u002F2023-10-05-Cplusplus教学\u002F0500-运算符","运算符",[7],"0500",{"path":4032,"stem":4033,"title":4034,"authors":4035,"date":3988,"chapterOrder":4036,"chapterDepth":4006,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F0600-cheng-xu-liu-cheng-jie-gou","wiki\u002F2023-10-05-Cplusplus教学\u002F0600-程序流程结构","程序流程结构",[7],"0600",{"path":4038,"stem":4039,"title":4040,"authors":4041,"date":3988,"chapterOrder":4042,"chapterDepth":4006,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F0700-shu-zu","wiki\u002F2023-10-05-Cplusplus教学\u002F0700-数组","数组",[7],"0700",{"path":4044,"stem":4045,"title":4046,"authors":4047,"date":3988,"chapterOrder":4048,"chapterDepth":4006,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F0800-han-shu-yu-tou-wen-jian","wiki\u002F2023-10-05-Cplusplus教学\u002F0800-函数与头文件","函数与头文件",[7],"0800",{"path":4050,"stem":4051,"title":4052,"authors":4053,"date":3988,"chapterOrder":4054,"chapterDepth":4006,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F0900-zhi-zhen","wiki\u002F2023-10-05-Cplusplus教学\u002F0900-指针","指针",[7],"0900",{"path":4056,"stem":4057,"title":4058,"authors":4059,"date":3988,"chapterOrder":4060,"chapterDepth":4006,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1000-jie-gou-ti-yu-gong-yong-ti","wiki\u002F2023-10-05-Cplusplus教学\u002F1000-结构体与共用体","结构体与共用体",[7],"1000",{"path":4062,"stem":4063,"title":4064,"authors":4065,"date":3988,"chapterOrder":4066,"chapterDepth":4006,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1100-nei-cun-fen-qu-yu-sheng-ming-zhou-qi","wiki\u002F2023-10-05-Cplusplus教学\u002F1100-内存分区与生命周期","内存分区与生命周期",[7],"1100",{"path":4068,"stem":4069,"title":4070,"authors":4071,"date":3988,"chapterOrder":4072,"chapterDepth":4006,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1200-yin-yong","wiki\u002F2023-10-05-Cplusplus教学\u002F1200-引用","引用",[7],"1200",{"path":4074,"stem":4075,"title":4076,"authors":4077,"date":3988,"chapterOrder":4078,"chapterDepth":4006,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1300-han-shu-ti-gao","wiki\u002F2023-10-05-Cplusplus教学\u002F1300-函数提高","函数提高",[7],"1300",{"path":4080,"stem":4081,"title":4082,"authors":4083,"date":3988,"chapterOrder":4084,"chapterDepth":4006,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1350-ming-ming-kong-jian","wiki\u002F2023-10-05-Cplusplus教学\u002F1350-命名空间","命名空间",[7],"1350",{"path":4086,"stem":4087,"title":4088,"authors":4089,"date":3988,"chapterOrder":4090,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1400-0100-feng-zhuang","wiki\u002F2023-10-05-Cplusplus教学\u002F1400-0100-封装","封装",[7],"1400-0100",{"path":4092,"stem":4093,"title":4094,"authors":4095,"date":3988,"chapterOrder":4096,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1400-0200-dui-xiang-chu-shi-hua-he-qing-li","wiki\u002F2023-10-05-Cplusplus教学\u002F1400-0200-对象初始化和清理","对象初始化和清理",[7],"1400-0200",{"path":4098,"stem":4099,"title":4100,"authors":4101,"date":3988,"chapterOrder":4102,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1400-0300-dui-xiang-mo-xing-yu-this-zhi-zhen","wiki\u002F2023-10-05-Cplusplus教学\u002F1400-0300-对象模型与this指针","对象模型与this指针",[7],"1400-0300",{"path":4104,"stem":4105,"title":4106,"authors":4107,"date":3988,"chapterOrder":4108,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1400-0400-you-yuan-yu-yun-suan-fu-zhong-zai","wiki\u002F2023-10-05-Cplusplus教学\u002F1400-0400-友元与运算符重载","友元与运算符重载",[7],"1400-0400",{"path":4110,"stem":4111,"title":4112,"authors":4113,"date":3988,"chapterOrder":4114,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1400-0500-ji-cheng","wiki\u002F2023-10-05-Cplusplus教学\u002F1400-0500-继承","继承",[7],"1400-0500",{"path":4116,"stem":4117,"title":4118,"authors":4119,"date":3988,"chapterOrder":4120,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1400-0600-duo-tai","wiki\u002F2023-10-05-Cplusplus教学\u002F1400-0600-多态","多态",[7],"1400-0600",{"path":4122,"stem":4123,"title":4124,"authors":4125,"date":3988,"chapterOrder":4126,"chapterDepth":4006,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1400-lei-he-dui-xiang","wiki\u002F2023-10-05-Cplusplus教学\u002F1400-类和对象","类和对象",[7],"1400",{"path":4128,"stem":4129,"title":4130,"authors":4131,"date":3988,"chapterOrder":4132,"chapterDepth":4006,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1450-han-shu-zhi-zhen","wiki\u002F2023-10-05-Cplusplus教学\u002F1450-函数指针","函数指针",[7],"1450",{"path":4134,"stem":4135,"title":4136,"authors":4137,"date":3988,"chapterOrder":4138,"chapterDepth":4006,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1500-wen-jian-cao-zuo","wiki\u002F2023-10-05-Cplusplus教学\u002F1500-文件操作","文件操作",[7],"1500",{"path":4140,"stem":4141,"title":4142,"authors":4143,"date":3988,"chapterOrder":4144,"chapterDepth":4006,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1600-yi-chang-chu-li-yu-cuo-wu-ma","wiki\u002F2023-10-05-Cplusplus教学\u002F1600-异常处理与错误码","异常处理",[7],"1600",{"path":4146,"stem":4147,"title":4148,"authors":4149,"date":3988,"chapterOrder":4150,"chapterDepth":4006,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1700-mu-ban","wiki\u002F2023-10-05-Cplusplus教学\u002F1700-模板","模板",[7],"1700",{"path":4152,"stem":4153,"title":4154,"authors":4155,"date":3988,"chapterOrder":4156,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1800-0100-stl-chu-shi","wiki\u002F2023-10-05-Cplusplus教学\u002F1800-0100-STL初识","STL初识",[7],"1800-0100",{"path":4158,"stem":4159,"title":4160,"authors":4161,"date":3988,"chapterOrder":4162,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1800-0200-std-array","wiki\u002F2023-10-05-Cplusplus教学\u002F1800-0200-std-array","std::array",[7],"1800-0200",{"path":4164,"stem":4165,"title":4166,"authors":4167,"date":3988,"chapterOrder":4168,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1800-0300-string-rong-qi","wiki\u002F2023-10-05-Cplusplus教学\u002F1800-0300-string容器","string容器",[7],"1800-0300",{"path":4170,"stem":4171,"title":4172,"authors":4173,"date":3988,"chapterOrder":4174,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1800-0400-vector-rong-qi","wiki\u002F2023-10-05-Cplusplus教学\u002F1800-0400-vector容器","vector 容器",[7],"1800-0400",{"path":4176,"stem":4177,"title":4178,"authors":4179,"date":3988,"chapterOrder":4180,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1800-0500-deque-rong-qi","wiki\u002F2023-10-05-Cplusplus教学\u002F1800-0500-deque容器","deque 容器",[7],"1800-0500",{"path":4182,"stem":4183,"title":4184,"authors":4185,"date":3988,"chapterOrder":4186,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1800-0600-stack-rong-qi","wiki\u002F2023-10-05-Cplusplus教学\u002F1800-0600-stack容器","stack 容器",[7],"1800-0600",{"path":4188,"stem":4189,"title":4190,"authors":4191,"date":3988,"chapterOrder":4192,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1800-0700-queue-rong-qi","wiki\u002F2023-10-05-Cplusplus教学\u002F1800-0700-queue容器","queue 容器",[7],"1800-0700",{"path":4194,"stem":4195,"title":4196,"authors":4197,"date":3988,"chapterOrder":4198,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1800-0800-list-rong-qi","wiki\u002F2023-10-05-Cplusplus教学\u002F1800-0800-list容器","list 容器",[7],"1800-0800",{"path":4200,"stem":4201,"title":4202,"authors":4203,"date":3988,"chapterOrder":4204,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1800-0900-set-rong-qi","wiki\u002F2023-10-05-Cplusplus教学\u002F1800-0900-set容器","set \u002F multiset 容器",[7],"1800-0900",{"path":4206,"stem":4207,"title":4208,"authors":4209,"date":3988,"chapterOrder":4210,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1800-1000-map-rong-qi","wiki\u002F2023-10-05-Cplusplus教学\u002F1800-1000-map容器","map \u002F multimap 容器",[7],"1800-1000",{"path":4212,"stem":4213,"title":4214,"authors":4215,"date":3988,"chapterOrder":4216,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1800-1100-han-shu-dui-xiang-yu-wei-ci","wiki\u002F2023-10-05-Cplusplus教学\u002F1800-1100-函数对象与谓词","函数对象与谓词",[7],"1800-1100",{"path":4218,"stem":4219,"title":4220,"authors":4221,"date":3988,"chapterOrder":4222,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1800-1200-chang-yong-suan-fa","wiki\u002F2023-10-05-Cplusplus教学\u002F1800-1200-常用算法","常用算法",[7],"1800-1200",{"path":4224,"stem":4225,"title":4226,"authors":4227,"date":3988,"chapterOrder":4228,"chapterDepth":4006,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1800-stl-ti-gao-bian-cheng","wiki\u002F2023-10-05-Cplusplus教学\u002F1800-STL提高编程","STL提高编程",[7],"1800",{"path":4230,"stem":4231,"title":4232,"authors":4233,"date":3988,"chapterOrder":4234,"chapterDepth":4006,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F1900-c-lei-xing-zhuan-huan","wiki\u002F2023-10-05-Cplusplus教学\u002F1900-C++类型转换","C++类型转换",[7],"1900",{"path":4236,"stem":4237,"title":4238,"authors":4239,"date":3988,"chapterOrder":4240,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-0100-auto","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-0100-auto","auto",[7],"2000-0100",{"path":4242,"stem":4243,"title":4244,"authors":4245,"date":3988,"chapterOrder":4246,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-0200-nullptr","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-0200-nullptr","nullptr",[7],"2000-0200",{"path":4248,"stem":4249,"title":365,"authors":4250,"date":3988,"chapterOrder":4251,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-0300-using","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-0300-using",[7],"2000-0300",{"path":4253,"stem":4254,"title":4255,"authors":4256,"date":3988,"chapterOrder":4257,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-0400-enum-class","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-0400-enum-class","enum class",[7],"2000-0400",{"path":4259,"stem":4260,"title":4261,"authors":4262,"date":3988,"chapterOrder":4263,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-0500-fan-wei-for-xun-huan","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-0500-范围for循环","范围 for 循环",[7],"2000-0500",{"path":4265,"stem":4266,"title":4267,"authors":4268,"date":3988,"chapterOrder":4269,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-0600-jie-gou-hua-bang-ding","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-0600-结构化绑定","结构化绑定",[7],"2000-0600",{"path":4271,"stem":4272,"title":4273,"authors":4274,"date":3988,"chapterOrder":4275,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-0700-constexpr","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-0700-constexpr","constexpr",[7],"2000-0700",{"path":4277,"stem":4278,"title":4279,"authors":4280,"date":3988,"chapterOrder":4281,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-0800-raii","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-0800-RAII","RAII",[7],"2000-0800",{"path":4283,"stem":4284,"title":4285,"authors":4286,"date":3988,"chapterOrder":4287,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-0900-zhi-neng-zhi-zhen","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-0900-智能指针","智能指针",[7],"2000-0900",{"path":4289,"stem":4290,"title":4291,"authors":4292,"date":3988,"chapterOrder":4293,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1000-you-zhi-yin-yong-he-yi-dong-yu-yi","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1000-右值引用和移动语义","右值引用和移动语义",[7],"2000-1000",{"path":4295,"stem":4296,"title":4297,"authors":4298,"date":3988,"chapterOrder":4299,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1100-lambda-biao-da-shi","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1100-Lambda表达式","Lambda 表达式",[7],"2000-1100",{"path":4301,"stem":4302,"title":4303,"authors":4304,"date":3988,"chapterOrder":4305,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1200-std-function","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1200-std-function","std::function",[7],"2000-1200",{"path":4307,"stem":4308,"title":4309,"authors":4310,"date":3988,"chapterOrder":4311,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1300-std-bind","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1300-std-bind","std::bind",[7],"2000-1300",{"path":4313,"stem":4314,"title":4315,"authors":4316,"date":3988,"chapterOrder":4317,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1400-std-optional","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1400-std-optional","std::optional",[7],"2000-1400",{"path":4319,"stem":4320,"title":4321,"authors":4322,"date":3988,"chapterOrder":4323,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1500-std-variant","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1500-std-variant","std::variant",[7],"2000-1500",{"path":4325,"stem":4326,"title":4327,"authors":4328,"date":3988,"chapterOrder":4329,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1600-std-span","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1600-std-span","std::span",[7],"2000-1600",{"path":4331,"stem":4332,"title":4333,"authors":4334,"date":3988,"chapterOrder":4335,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1700-std-format-print","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1700-std-format-print","std::format \u002F std::print",[7],"2000-1700",{"path":4337,"stem":4338,"title":4339,"authors":4340,"date":3988,"chapterOrder":4341,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1800-std-chrono","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1800-std-chrono","std::chrono",[7],"2000-1800",{"path":4343,"stem":4344,"title":4345,"authors":4346,"date":3988,"chapterOrder":4347,"chapterDepth":43,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1900-0100-bing-fa-shi-shen-me","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1900-0100-并发是什么","并发是什么",[7],"2000-1900-0100",{"path":4349,"stem":4350,"title":4351,"authors":4352,"date":3988,"chapterOrder":4353,"chapterDepth":43,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1900-0200-bing-xing-shi-shen-me","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1900-0200-并行是什么","并行是什么",[7],"2000-1900-0200",{"path":4355,"stem":4356,"title":4357,"authors":4358,"date":3988,"chapterOrder":4359,"chapterDepth":43,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1900-0300-xie-cheng-shi-shen-me","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1900-0300-协程是什么","协程是什么",[7],"2000-1900-0300",{"path":4361,"stem":4362,"title":4363,"authors":4364,"date":3988,"chapterOrder":4365,"chapterDepth":43,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1900-1000-bing-fa-bian-cheng","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1900-1000-并发编程","并发编程",[7],"2000-1900-1000",{"path":4367,"stem":4368,"title":4369,"authors":4370,"date":3988,"chapterOrder":4371,"chapterDepth":43,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1900-1100-std-thread","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1900-1100-std-thread","std::thread",[7],"2000-1900-1100",{"path":4373,"stem":4374,"title":4375,"authors":4376,"date":3988,"chapterOrder":4377,"chapterDepth":43,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1900-1200-mutex-lock-guard","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1900-1200-mutex-lock-guard","mutex 与 RAII 锁",[7],"2000-1900-1200",{"path":4379,"stem":4380,"title":4381,"authors":4382,"date":3988,"chapterOrder":4383,"chapterDepth":43,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1900-1300-std-atomic","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1900-1300-std-atomic","std::atomic",[7],"2000-1900-1300",{"path":4385,"stem":4386,"title":4387,"authors":4388,"date":3988,"chapterOrder":4389,"chapterDepth":43,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1900-1400-condition-variable","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1900-1400-condition-variable","condition_variable",[7],"2000-1900-1400",{"path":4391,"stem":4392,"title":4393,"authors":4394,"date":3988,"chapterOrder":4395,"chapterDepth":43,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1900-1500-future-async-promise","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1900-1500-future-async-promise","future、async、promise 与 packaged_task",[7],"2000-1900-1500",{"path":4397,"stem":4398,"title":4399,"authors":4400,"date":3988,"chapterOrder":4401,"chapterDepth":43,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1900-1600-jthread-stop-token","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1900-1600-jthread-stop-token","jthread 与 stop_token",[7],"2000-1900-1600",{"path":3995,"stem":3997,"title":5,"authors":4403,"date":3988,"chapterOrder":3987,"chapterDepth":43,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},[7],{"path":4405,"stem":4406,"title":4407,"authors":4408,"date":3988,"chapterOrder":4409,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-1900-bing-fa-bing-xing-yu-xie-cheng","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-1900-并发并行与协程","并发、并行与协程",[7],"2000-1900",{"path":4411,"stem":4412,"title":4413,"authors":4414,"date":3988,"chapterOrder":4415,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-2000-std-filesystem","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-2000-std-filesystem","std::filesystem",[7],"2000-2000",{"path":4417,"stem":4418,"title":4419,"authors":4420,"date":3988,"chapterOrder":4421,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-2100-modules-jian-jie","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-2100-modules简介","modules 简介",[7],"2000-2100",{"path":4423,"stem":4424,"title":4425,"authors":4426,"date":3988,"chapterOrder":4427,"chapterDepth":4006,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2000-xian-dai-c","wiki\u002F2023-10-05-Cplusplus教学\u002F2000-现代C++","现代C++",[7],"2000",{"path":4429,"stem":4430,"title":4431,"authors":4432,"date":3988,"chapterOrder":4433,"chapterDepth":43,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2100-0100-0100-ding-shi-qi-yu-yi-bu-io","wiki\u002F2023-10-05-Cplusplus教学\u002F2100-0100-0100-定时器与异步IO","定时器与异步 IO",[7],"2100-0100-0100",{"path":4435,"stem":4436,"title":4437,"authors":4438,"date":3988,"chapterOrder":4439,"chapterDepth":43,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2100-0100-0200-boost-asio-ji-chu","wiki\u002F2023-10-05-Cplusplus教学\u002F2100-0100-0200-Boost.Asio基础","Boost.Asio 基础",[7],"2100-0100-0200",{"path":4441,"stem":4442,"title":4443,"authors":4444,"date":3988,"chapterOrder":4445,"chapterDepth":43,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2100-0100-0300-chuan-kou-tong-xin","wiki\u002F2023-10-05-Cplusplus教学\u002F2100-0100-0300-串口通信","串口通信教学",[7],"2100-0100-0300",{"path":4447,"stem":4448,"title":4449,"authors":4450,"date":3988,"chapterOrder":4451,"chapterDepth":43,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2100-0100-0350-chuan-kou-tong-xin-chuan-kou-bao-xie-yi-shi-li","wiki\u002F2023-10-05-Cplusplus教学\u002F2100-0100-0350-串口通信串口包协议实例","串口通信串口包协议实例",[7],"2100-0100-0350",{"path":4453,"stem":4454,"title":4455,"authors":4456,"date":3988,"chapterOrder":4457,"chapterDepth":43,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2100-0100-0400-tcp-tong-xin","wiki\u002F2023-10-05-Cplusplus教学\u002F2100-0100-0400-TCP通信","TCP 通信",[7],"2100-0100-0400",{"path":4459,"stem":4460,"title":4461,"authors":4462,"date":3988,"chapterOrder":4463,"chapterDepth":43,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2100-0100-0500-udp-tong-xin","wiki\u002F2023-10-05-Cplusplus教学\u002F2100-0100-0500-UDP通信","UDP 通信",[7],"2100-0100-0500",{"path":4465,"stem":4466,"title":4467,"authors":4468,"date":3988,"chapterOrder":4469,"chapterDepth":43,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2100-0100-0600-ji-qi-ren-gong-cheng-xie-fa-yu-ros2-ji-cheng","wiki\u002F2023-10-05-Cplusplus教学\u002F2100-0100-0600-机器人工程写法与ROS2集成","机器人工程写法与 ROS2 集成",[7],"2100-0100-0600",{"path":4471,"stem":4472,"title":4473,"authors":4474,"date":3988,"chapterOrder":4475,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2100-0100-boost-asio-yi-bu-io-ku","wiki\u002F2023-10-05-Cplusplus教学\u002F2100-0100-Boost.Asio异步IO库","Boost.Asio异步IO库",[7],"2100-0100",{"path":4477,"stem":4478,"title":4479,"authors":4480,"date":3988,"chapterOrder":4481,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2100-0200-eigen-xian-xing-dai-shu-ku","wiki\u002F2023-10-05-Cplusplus教学\u002F2100-0200-Eigen线性代数库","Eigen线性代数库",[7],"2100-0200",{"path":4483,"stem":4484,"title":4485,"authors":4486,"date":3988,"chapterOrder":4487,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2100-0300-opencv-ji-suan-ji-shi-jue-ku","wiki\u002F2023-10-05-Cplusplus教学\u002F2100-0300-OpenCV计算机视觉库","OpenCV计算机视觉库",[7],"2100-0300",{"path":4489,"stem":4490,"title":4491,"authors":4492,"date":3988,"chapterOrder":4493,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2100-0400-pcl-dian-yun-ku","wiki\u002F2023-10-05-Cplusplus教学\u002F2100-0400-PCL点云库","PCL点云库",[7],"2100-0400",{"path":4495,"stem":4496,"title":4497,"authors":4498,"date":3988,"chapterOrder":4499,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2100-0500-sophus-li-qun-li-dai-shu-ku","wiki\u002F2023-10-05-Cplusplus教学\u002F2100-0500-Sophus李群李代数库","Sophus 李群李代数库",[7],"2100-0500",{"path":4501,"stem":4502,"title":4503,"authors":4504,"date":3988,"chapterOrder":4505,"chapterDepth":4006,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2100-chang-yong-ku","wiki\u002F2023-10-05-Cplusplus教学\u002F2100-常用库","常用库学习",[7],"2100",{"path":4507,"stem":4508,"title":4509,"authors":4510,"date":3988,"chapterOrder":4511,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2200-0100-cmakepresets-yu-gou-jian-an-zhuang","wiki\u002F2023-10-05-Cplusplus教学\u002F2200-0100-CMakePresets与构建安装","CMakePresets与构建安装",[7],"2200-0100",{"path":4513,"stem":4514,"title":4515,"authors":4516,"date":3988,"chapterOrder":4517,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2200-0200-ding-ceng-cmake-yu-gong-gong-bian-yi-xuan-xiang","wiki\u002F2023-10-05-Cplusplus教学\u002F2200-0200-顶层CMake与公共编译选项","顶层CMake与公共编译选项",[7],"2200-0200",{"path":4519,"stem":4520,"title":4521,"authors":4522,"date":3988,"chapterOrder":4523,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2200-0300-src-yu-lib-mo-kuai-cmake-xiang-jie","wiki\u002F2023-10-05-Cplusplus教学\u002F2200-0300-src与lib模块CMake详解","src与lib模块CMake详解",[7],"2200-0300",{"path":4525,"stem":4526,"title":4527,"authors":4528,"date":3988,"chapterOrder":4529,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2200-0400-di-san-fang-ku-yi-lai-xie-fa","wiki\u002F2023-10-05-Cplusplus教学\u002F2200-0400-第三方库依赖写法","第三方库依赖写法",[7],"2200-0400",{"path":4531,"stem":4532,"title":4533,"authors":4534,"date":3988,"chapterOrder":4535,"chapterDepth":29,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2200-0500-mu-ban-kuo-zhan-yu-chang-jian-wen-ti","wiki\u002F2023-10-05-Cplusplus教学\u002F2200-0500-模板扩展与常见问题","模板扩展与常见问题",[7],"2200-0500",{"path":4537,"stem":4538,"title":4539,"authors":4540,"date":3988,"chapterOrder":4541,"chapterDepth":4006,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":3993},"\u002Fwiki\u002F2023-10-05-cplusplus-jiao-xue\u002F2200-cmake-gong-cheng-mu-ban","wiki\u002F2023-10-05-Cplusplus教学\u002F2200-CMake工程模板","CMake工程模板",[7],"2200",{"path":3990,"stem":4543,"title":4544,"authors":4545,"date":3988,"chapterOrder":4546,"chapterDepth":4006,"docKey":3989,"docRoot":3990,"docTitle":3991,"isWikiDoc":358,"isWikiIndex":358},"wiki\u002F2023-10-05-Cplusplus教学\u002Findex","C\u002FC++教程",[7],null,[4548,4550,4553,4556],{"name":7,"image":4549},"\u002Fimages\u002Fmember_photo\u002F董佳辉.jpg",{"name":4551,"image":4552},"宫金良","\u002Fimages\u002Fmember_photo\u002F宫金良.jpg",{"name":4554,"image":4555},"巩丽","\u002Fimages\u002Fmember_photo\u002F巩丽.png",{"name":4557,"image":4558},"张彦斐","\u002Fimages\u002Fmember_photo\u002F张彦斐.jpg",1792431899383]