[{"data":1,"prerenderedAt":2729},["ShallowReactive",2],{"page-\u002Frust\u002F22-concurrency":3},{"id":4,"title":5,"body":6,"description":2722,"extension":2723,"meta":2724,"navigation":224,"path":2725,"seo":2726,"stem":2727,"__hash__":2728},"content\u002Frust\u002F22-concurrency.md","22 — Concurrency & Multithreading",{"type":7,"value":8,"toc":2690},"minimark",[9,13,31,39,60,72,75,163,167,427,457,461,564,572,583,847,855,862,1024,1028,1034,1200,1205,1315,1319,1339,1343,1352,1399,1408,1411,1495,1505,1510,1831,1837,1842,1899,1908,1993,1997,2015,2132,2136,2171,2184,2188,2305,2308,2312,2326,2340,2346,2464,2470,2474,2575,2579,2631,2635,2654,2658,2683,2686],[10,11,5],"h1",{"id":12},"_22-concurrency-multithreading",[14,15,16,17,21,22,26,27,30],"p",{},"Rust's promise: ",[18,19,20],"strong",{},"fearless concurrency",". The type system prevents data races at compile time via ",[23,24,25],"code",{},"Send"," and ",[23,28,29],{},"Sync",".",[32,33,35,26,37],"h2",{"id":34},"send-and-sync",[23,36,25],{},[23,38,29],{},[40,41,42,48],"ul",{},[43,44,45,47],"li",{},[23,46,25],{},": a type can be transferred across threads (ownership moves safely).",[43,49,50,52,53,56,57,59],{},[23,51,29],{},": ",[23,54,55],{},"&T"," can be shared across threads (multiple threads can hold ",[23,58,55],{}," simultaneously).",[14,61,62,63,66,67,69,70,30],{},"They're ",[18,64,65],{},"auto-traits",": the compiler implements them automatically when all fields are ",[23,68,25],{},"\u002F",[23,71,29],{},[14,73,74],{},"Examples:",[40,76,77,92,104,115,133,145],{},[43,78,79,82,83,82,86,52,89,30],{},[23,80,81],{},"i32",", ",[23,84,85],{},"String",[23,87,88],{},"Vec\u003CT>",[23,90,91],{},"Send + Sync",[43,93,94,97,98,100,101,103],{},[23,95,96],{},"Rc\u003CT>",": not ",[23,99,29],{}," (shared non-atomic refcount), not ",[23,102,25],{}," (cheap counter).",[43,105,106,52,109,111,112,30],{},[23,107,108],{},"Arc\u003CT>",[23,110,91],{}," if ",[23,113,114],{},"T: Send + Sync",[43,116,117,69,120,52,123,125,126,129,130,132],{},[23,118,119],{},"Cell\u003CT>",[23,121,122],{},"RefCell\u003CT>",[23,124,25],{}," (if ",[23,127,128],{},"T: Send",") but not ",[23,131,29],{}," (no synchronization).",[43,134,135,69,138,52,141,111,143,30],{},[23,136,137],{},"Mutex\u003CT>",[23,139,140],{},"RwLock\u003CT>",[23,142,91],{},[23,144,128],{},[43,146,147,148,69,151,97,154,69,156,158,159,162],{},"Raw pointers ",[23,149,150],{},"*const T",[23,152,153],{},"*mut T",[23,155,25],{},[23,157,29],{}," (the compiler is conservative; opt in with ",[23,160,161],{},"unsafe impl",").",[32,164,166],{"id":165},"spawning-threads","Spawning Threads",[168,169,171],"code-wrapper",{"language":170},"rust",[172,173,177],"pre",{"className":174,"code":175,"language":170,"meta":176,"style":176},"language-rust shiki shiki-themes github-light github-dark","use std::thread;\nuse std::time::Duration;\n\nlet handle = thread::spawn(|| {\n    for i in 0..5 {\n        println!(\"thread: {i}\");\n        thread::sleep(Duration::from_millis(10));\n    }\n});\n\nfor i in 0..5 {\n    println!(\"main: {i}\");\n    thread::sleep(Duration::from_millis(10));\n}\n\nhandle.join().unwrap();\n","",[23,178,179,199,219,226,255,279,294,322,328,334,339,357,370,394,400,405],{"__ignoreMap":176},[180,181,184,188,192,195],"span",{"class":182,"line":183},"line",1,[180,185,187],{"class":186},"svdQ7","use",[180,189,191],{"class":190},"sIsaT"," std",[180,193,194],{"class":186},"::",[180,196,198],{"class":197},"ssxIu","thread;\n",[180,200,202,204,206,208,211,213,216],{"class":182,"line":201},2,[180,203,187],{"class":186},[180,205,191],{"class":190},[180,207,194],{"class":186},[180,209,210],{"class":190},"time",[180,212,194],{"class":186},[180,214,215],{"class":190},"Duration",[180,217,218],{"class":197},";\n",[180,220,222],{"class":182,"line":221},3,[180,223,225],{"emptyLinePlaceholder":224},true,"\n",[180,227,229,232,235,238,241,243,246,249,252],{"class":182,"line":228},4,[180,230,231],{"class":186},"let",[180,233,234],{"class":197}," handle ",[180,236,237],{"class":186},"=",[180,239,240],{"class":190}," thread",[180,242,194],{"class":186},[180,244,245],{"class":190},"spawn",[180,247,248],{"class":197},"(",[180,250,251],{"class":186},"||",[180,253,254],{"class":197}," {\n",[180,256,258,261,264,267,271,274,277],{"class":182,"line":257},5,[180,259,260],{"class":186},"    for",[180,262,263],{"class":197}," i ",[180,265,266],{"class":186},"in",[180,268,270],{"class":269},"snvgF"," 0",[180,272,273],{"class":186},"..",[180,275,276],{"class":269},"5",[180,278,254],{"class":197},[180,280,282,285,287,291],{"class":182,"line":281},6,[180,283,284],{"class":190},"        println!",[180,286,248],{"class":197},[180,288,290],{"class":289},"sJ6F3","\"thread: {i}\"",[180,292,293],{"class":197},");\n",[180,295,297,300,302,305,307,309,311,314,316,319],{"class":182,"line":296},7,[180,298,299],{"class":190},"        thread",[180,301,194],{"class":186},[180,303,304],{"class":190},"sleep",[180,306,248],{"class":197},[180,308,215],{"class":190},[180,310,194],{"class":186},[180,312,313],{"class":190},"from_millis",[180,315,248],{"class":197},[180,317,318],{"class":269},"10",[180,320,321],{"class":197},"));\n",[180,323,325],{"class":182,"line":324},8,[180,326,327],{"class":197},"    }\n",[180,329,331],{"class":182,"line":330},9,[180,332,333],{"class":197},"});\n",[180,335,337],{"class":182,"line":336},10,[180,338,225],{"emptyLinePlaceholder":224},[180,340,342,345,347,349,351,353,355],{"class":182,"line":341},11,[180,343,344],{"class":186},"for",[180,346,263],{"class":197},[180,348,266],{"class":186},[180,350,270],{"class":269},[180,352,273],{"class":186},[180,354,276],{"class":269},[180,356,254],{"class":197},[180,358,360,363,365,368],{"class":182,"line":359},12,[180,361,362],{"class":190},"    println!",[180,364,248],{"class":197},[180,366,367],{"class":289},"\"main: {i}\"",[180,369,293],{"class":197},[180,371,373,376,378,380,382,384,386,388,390,392],{"class":182,"line":372},13,[180,374,375],{"class":190},"    thread",[180,377,194],{"class":186},[180,379,304],{"class":190},[180,381,248],{"class":197},[180,383,215],{"class":190},[180,385,194],{"class":186},[180,387,313],{"class":190},[180,389,248],{"class":197},[180,391,318],{"class":269},[180,393,321],{"class":197},[180,395,397],{"class":182,"line":396},14,[180,398,399],{"class":197},"}\n",[180,401,403],{"class":182,"line":402},15,[180,404,225],{"emptyLinePlaceholder":224},[180,406,408,411,413,416,419,421,424],{"class":182,"line":407},16,[180,409,410],{"class":197},"handle",[180,412,30],{"class":186},[180,414,415],{"class":190},"join",[180,417,418],{"class":197},"()",[180,420,30],{"class":186},[180,422,423],{"class":190},"unwrap",[180,425,426],{"class":197},"();\n",[40,428,429,438,451],{},[43,430,431,434,435,30],{},[23,432,433],{},"thread::spawn"," returns a ",[23,436,437],{},"JoinHandle\u003CT>",[43,439,440,443,444,447,448,162],{},[23,441,442],{},".join()"," blocks until the thread exits, returning ",[23,445,446],{},"Result\u003CT, Box\u003Cdyn Any + Send>>"," (panic propagates as ",[23,449,450],{},"Err",[43,452,453,454,30],{},"Closures must be ",[23,455,456],{},"'static + Send",[32,458,460],{"id":459},"moving-data-into-threads","Moving Data into Threads",[168,462,463],{"language":170},[172,464,466],{"className":174,"code":465,"language":170,"meta":176,"style":176},"let data = vec![1, 2, 3];\nlet handle = thread::spawn(move || {\n    println!(\"{:?}\", data);   \u002F\u002F data moved in\n});\n\u002F\u002F data not accessible here\nhandle.join().unwrap();\n",[23,467,468,499,523,539,543,548],{"__ignoreMap":176},[180,469,470,472,475,477,480,483,486,488,491,493,496],{"class":182,"line":183},[180,471,231],{"class":186},[180,473,474],{"class":197}," data ",[180,476,237],{"class":186},[180,478,479],{"class":190}," vec!",[180,481,482],{"class":197},"[",[180,484,485],{"class":269},"1",[180,487,82],{"class":197},[180,489,490],{"class":269},"2",[180,492,82],{"class":197},[180,494,495],{"class":269},"3",[180,497,498],{"class":197},"];\n",[180,500,501,503,505,507,509,511,513,515,518,521],{"class":182,"line":201},[180,502,231],{"class":186},[180,504,234],{"class":197},[180,506,237],{"class":186},[180,508,240],{"class":190},[180,510,194],{"class":186},[180,512,245],{"class":190},[180,514,248],{"class":197},[180,516,517],{"class":186},"move",[180,519,520],{"class":186}," ||",[180,522,254],{"class":197},[180,524,525,527,529,532,535],{"class":182,"line":221},[180,526,362],{"class":190},[180,528,248],{"class":197},[180,530,531],{"class":289},"\"{:?}\"",[180,533,534],{"class":197},", data);   ",[180,536,538],{"class":537},"sdCPZ","\u002F\u002F data moved in\n",[180,540,541],{"class":182,"line":228},[180,542,333],{"class":197},[180,544,545],{"class":182,"line":257},[180,546,547],{"class":537},"\u002F\u002F data not accessible here\n",[180,549,550,552,554,556,558,560,562],{"class":182,"line":281},[180,551,410],{"class":197},[180,553,30],{"class":186},[180,555,415],{"class":190},[180,557,418],{"class":197},[180,559,30],{"class":186},[180,561,423],{"class":190},[180,563,426],{"class":197},[14,565,566,568,569,162],{},[23,567,517],{}," is almost always required — captures must outlive the thread (",[23,570,571],{},"'static",[32,573,575,576,579,580],{"id":574},"shared-state-with-arc-mutex","Shared State with ",[23,577,578],{},"Arc"," + ",[23,581,582],{},"Mutex",[168,584,585],{"language":170},[172,586,588],{"className":174,"code":587,"language":170,"meta":176,"style":176},"use std::sync::{Arc, Mutex};\nuse std::thread;\n\nlet counter = Arc::new(Mutex::new(0));\nlet mut handles = vec![];\n\nfor _ in 0..10 {\n    let counter = Arc::clone(&counter);\n    handles.push(thread::spawn(move || {\n        let mut n = counter.lock().unwrap();\n        *n += 1;\n    }));\n}\n\nfor h in handles { h.join().unwrap(); }\nprintln!(\"{:?}\", counter);   \u002F\u002F 10\n",[23,589,590,615,625,629,661,678,682,699,723,750,778,794,799,803,807,832],{"__ignoreMap":176},[180,591,592,594,596,598,601,603,606,608,610,612],{"class":182,"line":183},[180,593,187],{"class":186},[180,595,191],{"class":190},[180,597,194],{"class":186},[180,599,600],{"class":190},"sync",[180,602,194],{"class":186},[180,604,605],{"class":197},"{",[180,607,578],{"class":190},[180,609,82],{"class":197},[180,611,582],{"class":190},[180,613,614],{"class":197},"};\n",[180,616,617,619,621,623],{"class":182,"line":201},[180,618,187],{"class":186},[180,620,191],{"class":190},[180,622,194],{"class":186},[180,624,198],{"class":197},[180,626,627],{"class":182,"line":221},[180,628,225],{"emptyLinePlaceholder":224},[180,630,631,633,636,638,641,643,646,648,650,652,654,656,659],{"class":182,"line":228},[180,632,231],{"class":186},[180,634,635],{"class":197}," counter ",[180,637,237],{"class":186},[180,639,640],{"class":190}," Arc",[180,642,194],{"class":186},[180,644,645],{"class":190},"new",[180,647,248],{"class":197},[180,649,582],{"class":190},[180,651,194],{"class":186},[180,653,645],{"class":190},[180,655,248],{"class":197},[180,657,658],{"class":269},"0",[180,660,321],{"class":197},[180,662,663,665,668,671,673,675],{"class":182,"line":257},[180,664,231],{"class":186},[180,666,667],{"class":186}," mut",[180,669,670],{"class":197}," handles ",[180,672,237],{"class":186},[180,674,479],{"class":190},[180,676,677],{"class":197},"[];\n",[180,679,680],{"class":182,"line":281},[180,681,225],{"emptyLinePlaceholder":224},[180,683,684,686,689,691,693,695,697],{"class":182,"line":296},[180,685,344],{"class":186},[180,687,688],{"class":197}," _ ",[180,690,266],{"class":186},[180,692,270],{"class":269},[180,694,273],{"class":186},[180,696,318],{"class":269},[180,698,254],{"class":197},[180,700,701,704,706,708,710,712,715,717,720],{"class":182,"line":324},[180,702,703],{"class":186},"    let",[180,705,635],{"class":197},[180,707,237],{"class":186},[180,709,640],{"class":190},[180,711,194],{"class":186},[180,713,714],{"class":190},"clone",[180,716,248],{"class":197},[180,718,719],{"class":186},"&",[180,721,722],{"class":197},"counter);\n",[180,724,725,728,730,733,735,738,740,742,744,746,748],{"class":182,"line":330},[180,726,727],{"class":197},"    handles",[180,729,30],{"class":186},[180,731,732],{"class":190},"push",[180,734,248],{"class":197},[180,736,737],{"class":190},"thread",[180,739,194],{"class":186},[180,741,245],{"class":190},[180,743,248],{"class":197},[180,745,517],{"class":186},[180,747,520],{"class":186},[180,749,254],{"class":197},[180,751,752,755,757,760,762,765,767,770,772,774,776],{"class":182,"line":336},[180,753,754],{"class":186},"        let",[180,756,667],{"class":186},[180,758,759],{"class":197}," n ",[180,761,237],{"class":186},[180,763,764],{"class":197}," counter",[180,766,30],{"class":186},[180,768,769],{"class":190},"lock",[180,771,418],{"class":197},[180,773,30],{"class":186},[180,775,423],{"class":190},[180,777,426],{"class":197},[180,779,780,783,786,789,792],{"class":182,"line":341},[180,781,782],{"class":186},"        *",[180,784,785],{"class":197},"n ",[180,787,788],{"class":186},"+=",[180,790,791],{"class":269}," 1",[180,793,218],{"class":197},[180,795,796],{"class":182,"line":359},[180,797,798],{"class":197},"    }));\n",[180,800,801],{"class":182,"line":372},[180,802,399],{"class":197},[180,804,805],{"class":182,"line":396},[180,806,225],{"emptyLinePlaceholder":224},[180,808,809,811,814,816,819,821,823,825,827,829],{"class":182,"line":402},[180,810,344],{"class":186},[180,812,813],{"class":197}," h ",[180,815,266],{"class":186},[180,817,818],{"class":197}," handles { h",[180,820,30],{"class":186},[180,822,415],{"class":190},[180,824,418],{"class":197},[180,826,30],{"class":186},[180,828,423],{"class":190},[180,830,831],{"class":197},"(); }\n",[180,833,834,837,839,841,844],{"class":182,"line":407},[180,835,836],{"class":190},"println!",[180,838,248],{"class":197},[180,840,531],{"class":289},[180,842,843],{"class":197},", counter);   ",[180,845,846],{"class":537},"\u002F\u002F 10\n",[14,848,849,851,852,854],{},[23,850,578],{}," for shared ownership; ",[23,853,582],{}," for synchronized mutation. Lock guards auto-unlock on drop (RAII).",[32,856,858,861],{"id":857},"rwlock-for-read-heavy-workloads",[23,859,860],{},"RwLock"," for Read-Heavy Workloads",[168,863,864],{"language":170},[172,865,867],{"className":174,"code":866,"language":170,"meta":176,"style":176},"use std::sync::RwLock;\nlet lock = RwLock::new(0);\n\nlet r1 = lock.read().unwrap();\nlet r2 = lock.read().unwrap();   \u002F\u002F multiple readers OK\n\u002F\u002F let w = lock.write().unwrap();   \u002F\u002F would block above\ndrop(r1); drop(r2);\nlet mut w = lock.write().unwrap();\n*w += 1;\n",[23,868,869,885,907,911,936,963,971,984,1010],{"__ignoreMap":176},[180,870,871,873,875,877,879,881,883],{"class":182,"line":183},[180,872,187],{"class":186},[180,874,191],{"class":190},[180,876,194],{"class":186},[180,878,600],{"class":190},[180,880,194],{"class":186},[180,882,860],{"class":190},[180,884,218],{"class":197},[180,886,887,889,892,894,897,899,901,903,905],{"class":182,"line":201},[180,888,231],{"class":186},[180,890,891],{"class":197}," lock ",[180,893,237],{"class":186},[180,895,896],{"class":190}," RwLock",[180,898,194],{"class":186},[180,900,645],{"class":190},[180,902,248],{"class":197},[180,904,658],{"class":269},[180,906,293],{"class":197},[180,908,909],{"class":182,"line":221},[180,910,225],{"emptyLinePlaceholder":224},[180,912,913,915,918,920,923,925,928,930,932,934],{"class":182,"line":228},[180,914,231],{"class":186},[180,916,917],{"class":197}," r1 ",[180,919,237],{"class":186},[180,921,922],{"class":197}," lock",[180,924,30],{"class":186},[180,926,927],{"class":190},"read",[180,929,418],{"class":197},[180,931,30],{"class":186},[180,933,423],{"class":190},[180,935,426],{"class":197},[180,937,938,940,943,945,947,949,951,953,955,957,960],{"class":182,"line":257},[180,939,231],{"class":186},[180,941,942],{"class":197}," r2 ",[180,944,237],{"class":186},[180,946,922],{"class":197},[180,948,30],{"class":186},[180,950,927],{"class":190},[180,952,418],{"class":197},[180,954,30],{"class":186},[180,956,423],{"class":190},[180,958,959],{"class":197},"();   ",[180,961,962],{"class":537},"\u002F\u002F multiple readers OK\n",[180,964,965,968],{"class":182,"line":281},[180,966,967],{"class":537},"\u002F\u002F let w = lock.write().unwrap();",[180,969,970],{"class":537},"   \u002F\u002F would block above\n",[180,972,973,976,979,981],{"class":182,"line":296},[180,974,975],{"class":190},"drop",[180,977,978],{"class":197},"(r1); ",[180,980,975],{"class":190},[180,982,983],{"class":197},"(r2);\n",[180,985,986,988,990,993,995,997,999,1002,1004,1006,1008],{"class":182,"line":324},[180,987,231],{"class":186},[180,989,667],{"class":186},[180,991,992],{"class":197}," w ",[180,994,237],{"class":186},[180,996,922],{"class":197},[180,998,30],{"class":186},[180,1000,1001],{"class":190},"write",[180,1003,418],{"class":197},[180,1005,30],{"class":186},[180,1007,423],{"class":190},[180,1009,426],{"class":197},[180,1011,1012,1015,1018,1020,1022],{"class":182,"line":330},[180,1013,1014],{"class":186},"*",[180,1016,1017],{"class":197},"w ",[180,1019,788],{"class":186},[180,1021,791],{"class":269},[180,1023,218],{"class":197},[32,1025,1027],{"id":1026},"channel-message-passing","Channel — Message Passing",[14,1029,1030,1033],{},[23,1031,1032],{},"std::sync::mpsc"," (multi-producer, single-consumer):",[168,1035,1036],{"language":170},[172,1037,1039],{"className":174,"code":1038,"language":170,"meta":176,"style":176},"use std::sync::mpsc;\nuse std::thread;\n\nlet (tx, rx) = mpsc::channel();\n\nlet h = thread::spawn(move || {\n    let v = rx.recv().unwrap();\n    println!(\"got {v}\");\n});\n\ntx.send(42).unwrap();\nh.join().unwrap();\n",[23,1040,1041,1056,1066,1070,1089,1093,1115,1140,1151,1155,1159,1183],{"__ignoreMap":176},[180,1042,1043,1045,1047,1049,1051,1053],{"class":182,"line":183},[180,1044,187],{"class":186},[180,1046,191],{"class":190},[180,1048,194],{"class":186},[180,1050,600],{"class":190},[180,1052,194],{"class":186},[180,1054,1055],{"class":197},"mpsc;\n",[180,1057,1058,1060,1062,1064],{"class":182,"line":201},[180,1059,187],{"class":186},[180,1061,191],{"class":190},[180,1063,194],{"class":186},[180,1065,198],{"class":197},[180,1067,1068],{"class":182,"line":221},[180,1069,225],{"emptyLinePlaceholder":224},[180,1071,1072,1074,1077,1079,1082,1084,1087],{"class":182,"line":228},[180,1073,231],{"class":186},[180,1075,1076],{"class":197}," (tx, rx) ",[180,1078,237],{"class":186},[180,1080,1081],{"class":190}," mpsc",[180,1083,194],{"class":186},[180,1085,1086],{"class":190},"channel",[180,1088,426],{"class":197},[180,1090,1091],{"class":182,"line":257},[180,1092,225],{"emptyLinePlaceholder":224},[180,1094,1095,1097,1099,1101,1103,1105,1107,1109,1111,1113],{"class":182,"line":281},[180,1096,231],{"class":186},[180,1098,813],{"class":197},[180,1100,237],{"class":186},[180,1102,240],{"class":190},[180,1104,194],{"class":186},[180,1106,245],{"class":190},[180,1108,248],{"class":197},[180,1110,517],{"class":186},[180,1112,520],{"class":186},[180,1114,254],{"class":197},[180,1116,1117,1119,1122,1124,1127,1129,1132,1134,1136,1138],{"class":182,"line":296},[180,1118,703],{"class":186},[180,1120,1121],{"class":197}," v ",[180,1123,237],{"class":186},[180,1125,1126],{"class":197}," rx",[180,1128,30],{"class":186},[180,1130,1131],{"class":190},"recv",[180,1133,418],{"class":197},[180,1135,30],{"class":186},[180,1137,423],{"class":190},[180,1139,426],{"class":197},[180,1141,1142,1144,1146,1149],{"class":182,"line":324},[180,1143,362],{"class":190},[180,1145,248],{"class":197},[180,1147,1148],{"class":289},"\"got {v}\"",[180,1150,293],{"class":197},[180,1152,1153],{"class":182,"line":330},[180,1154,333],{"class":197},[180,1156,1157],{"class":182,"line":336},[180,1158,225],{"emptyLinePlaceholder":224},[180,1160,1161,1164,1166,1169,1171,1174,1177,1179,1181],{"class":182,"line":341},[180,1162,1163],{"class":197},"tx",[180,1165,30],{"class":186},[180,1167,1168],{"class":190},"send",[180,1170,248],{"class":197},[180,1172,1173],{"class":269},"42",[180,1175,1176],{"class":197},")",[180,1178,30],{"class":186},[180,1180,423],{"class":190},[180,1182,426],{"class":197},[180,1184,1185,1188,1190,1192,1194,1196,1198],{"class":182,"line":359},[180,1186,1187],{"class":197},"h",[180,1189,30],{"class":186},[180,1191,415],{"class":190},[180,1193,418],{"class":197},[180,1195,30],{"class":186},[180,1197,423],{"class":190},[180,1199,426],{"class":197},[1201,1202,1204],"h3",{"id":1203},"multi-producer","Multi-Producer",[168,1206,1207],{"language":170},[172,1208,1210],{"className":174,"code":1209,"language":170,"meta":176,"style":176},"let (tx, rx) = mpsc::channel();\nlet tx2 = tx.clone();   \u002F\u002F multiple senders\nthread::spawn(move || tx.send(1).unwrap());\nthread::spawn(move || tx2.send(2).unwrap());\n",[23,1211,1212,1228,1249,1282],{"__ignoreMap":176},[180,1213,1214,1216,1218,1220,1222,1224,1226],{"class":182,"line":183},[180,1215,231],{"class":186},[180,1217,1076],{"class":197},[180,1219,237],{"class":186},[180,1221,1081],{"class":190},[180,1223,194],{"class":186},[180,1225,1086],{"class":190},[180,1227,426],{"class":197},[180,1229,1230,1232,1235,1237,1240,1242,1244,1246],{"class":182,"line":201},[180,1231,231],{"class":186},[180,1233,1234],{"class":197}," tx2 ",[180,1236,237],{"class":186},[180,1238,1239],{"class":197}," tx",[180,1241,30],{"class":186},[180,1243,714],{"class":190},[180,1245,959],{"class":197},[180,1247,1248],{"class":537},"\u002F\u002F multiple senders\n",[180,1250,1251,1253,1255,1257,1259,1261,1263,1265,1267,1269,1271,1273,1275,1277,1279],{"class":182,"line":221},[180,1252,737],{"class":190},[180,1254,194],{"class":186},[180,1256,245],{"class":190},[180,1258,248],{"class":197},[180,1260,517],{"class":186},[180,1262,520],{"class":186},[180,1264,1239],{"class":197},[180,1266,30],{"class":186},[180,1268,1168],{"class":190},[180,1270,248],{"class":197},[180,1272,485],{"class":269},[180,1274,1176],{"class":197},[180,1276,30],{"class":186},[180,1278,423],{"class":190},[180,1280,1281],{"class":197},"());\n",[180,1283,1284,1286,1288,1290,1292,1294,1296,1299,1301,1303,1305,1307,1309,1311,1313],{"class":182,"line":228},[180,1285,737],{"class":190},[180,1287,194],{"class":186},[180,1289,245],{"class":190},[180,1291,248],{"class":197},[180,1293,517],{"class":186},[180,1295,520],{"class":186},[180,1297,1298],{"class":197}," tx2",[180,1300,30],{"class":186},[180,1302,1168],{"class":190},[180,1304,248],{"class":197},[180,1306,490],{"class":269},[180,1308,1176],{"class":197},[180,1310,30],{"class":186},[180,1312,423],{"class":190},[180,1314,1281],{"class":197},[1201,1316,1318],{"id":1317},"sync-vs-async-channels","Sync vs Async Channels",[40,1320,1321,1330],{},[43,1322,1323,1326,1327,1329],{},[23,1324,1325],{},"channel()",": unbounded, ",[23,1328,1168],{}," never blocks.",[43,1331,1332,1335,1336,1338],{},[23,1333,1334],{},"sync_channel(n)",": bounded; ",[23,1337,1168],{}," blocks when buffer full (backpressure).",[1201,1340,1342],{"id":1341},"crossbeam-channels","Crossbeam Channels",[14,1344,1345,1348,1349,30],{},[23,1346,1347],{},"crossbeam-channel"," is more featureful: bounded\u002Funbounded, select, after\u002Ftimeout, easy multi-consumer. Often preferred over ",[23,1350,1351],{},"std::mpsc",[168,1353,1354],{"language":170},[172,1355,1357],{"className":174,"code":1356,"language":170,"meta":176,"style":176},"let (s, r) = crossbeam_channel::unbounded();\ns.send(5).unwrap();\n",[23,1358,1359,1378],{"__ignoreMap":176},[180,1360,1361,1363,1366,1368,1371,1373,1376],{"class":182,"line":183},[180,1362,231],{"class":186},[180,1364,1365],{"class":197}," (s, r) ",[180,1367,237],{"class":186},[180,1369,1370],{"class":190}," crossbeam_channel",[180,1372,194],{"class":186},[180,1374,1375],{"class":190},"unbounded",[180,1377,426],{"class":197},[180,1379,1380,1383,1385,1387,1389,1391,1393,1395,1397],{"class":182,"line":201},[180,1381,1382],{"class":197},"s",[180,1384,30],{"class":186},[180,1386,1168],{"class":190},[180,1388,248],{"class":197},[180,1390,276],{"class":269},[180,1392,1176],{"class":197},[180,1394,30],{"class":186},[180,1396,423],{"class":190},[180,1398,426],{"class":197},[32,1400,1402,26,1405],{"id":1401},"park-and-unpark",[23,1403,1404],{},"park",[23,1406,1407],{},"unpark",[14,1409,1410],{},"Threads can be paused and woken:",[168,1412,1413],{"language":170},[172,1414,1416],{"className":174,"code":1415,"language":170,"meta":176,"style":176},"let h = thread::spawn(|| {\n    thread::park();\n    println!(\"unparked\");\n});\nh.thread().unpark();\nh.join().unwrap();\n",[23,1417,1418,1438,1448,1459,1463,1479],{"__ignoreMap":176},[180,1419,1420,1422,1424,1426,1428,1430,1432,1434,1436],{"class":182,"line":183},[180,1421,231],{"class":186},[180,1423,813],{"class":197},[180,1425,237],{"class":186},[180,1427,240],{"class":190},[180,1429,194],{"class":186},[180,1431,245],{"class":190},[180,1433,248],{"class":197},[180,1435,251],{"class":186},[180,1437,254],{"class":197},[180,1439,1440,1442,1444,1446],{"class":182,"line":201},[180,1441,375],{"class":190},[180,1443,194],{"class":186},[180,1445,1404],{"class":190},[180,1447,426],{"class":197},[180,1449,1450,1452,1454,1457],{"class":182,"line":221},[180,1451,362],{"class":190},[180,1453,248],{"class":197},[180,1455,1456],{"class":289},"\"unparked\"",[180,1458,293],{"class":197},[180,1460,1461],{"class":182,"line":228},[180,1462,333],{"class":197},[180,1464,1465,1467,1469,1471,1473,1475,1477],{"class":182,"line":257},[180,1466,1187],{"class":197},[180,1468,30],{"class":186},[180,1470,737],{"class":190},[180,1472,418],{"class":197},[180,1474,30],{"class":186},[180,1476,1407],{"class":190},[180,1478,426],{"class":197},[180,1480,1481,1483,1485,1487,1489,1491,1493],{"class":182,"line":281},[180,1482,1187],{"class":197},[180,1484,30],{"class":186},[180,1486,415],{"class":190},[180,1488,418],{"class":197},[180,1490,30],{"class":186},[180,1492,423],{"class":190},[180,1494,426],{"class":197},[14,1496,1497,1498,1501,1502,30],{},"Low-level synchronization — usually use channels, ",[23,1499,1500],{},"Condvar",", or ",[23,1503,1504],{},"Barrier",[32,1506,1508],{"id":1507},"condvar",[23,1509,1500],{},[168,1511,1512],{"language":170},[172,1513,1515],{"className":174,"code":1514,"language":170,"meta":176,"style":176},"use std::sync::{Arc, Mutex, Condvar};\n\nlet pair = Arc::new((Mutex::new(false), Condvar::new()));\nlet (lock, cvar) = Arc::clone(&pair);\n\nlet h = thread::spawn(move || {\n    let (mut started, cvar) = (&lock.0.lock().unwrap(), &lock.1);\n    while !*started {\n        started = cvar.wait(started).unwrap();\n    }\n});\n\n{\n    let (mut started, cvar) = (&lock.0.lock().unwrap(), &lock.1);\n    *started = true;\n    cvar.notify_one();\n}\n\nh.join().unwrap();\n",[23,1516,1517,1543,1547,1588,1610,1614,1636,1683,1694,1718,1722,1726,1730,1735,1777,1792,1804,1809,1814],{"__ignoreMap":176},[180,1518,1519,1521,1523,1525,1527,1529,1531,1533,1535,1537,1539,1541],{"class":182,"line":183},[180,1520,187],{"class":186},[180,1522,191],{"class":190},[180,1524,194],{"class":186},[180,1526,600],{"class":190},[180,1528,194],{"class":186},[180,1530,605],{"class":197},[180,1532,578],{"class":190},[180,1534,82],{"class":197},[180,1536,582],{"class":190},[180,1538,82],{"class":197},[180,1540,1500],{"class":190},[180,1542,614],{"class":197},[180,1544,1545],{"class":182,"line":201},[180,1546,225],{"emptyLinePlaceholder":224},[180,1548,1549,1551,1554,1556,1558,1560,1562,1565,1567,1569,1571,1573,1576,1579,1581,1583,1585],{"class":182,"line":221},[180,1550,231],{"class":186},[180,1552,1553],{"class":197}," pair ",[180,1555,237],{"class":186},[180,1557,640],{"class":190},[180,1559,194],{"class":186},[180,1561,645],{"class":190},[180,1563,1564],{"class":197},"((",[180,1566,582],{"class":190},[180,1568,194],{"class":186},[180,1570,645],{"class":190},[180,1572,248],{"class":197},[180,1574,1575],{"class":269},"false",[180,1577,1578],{"class":197},"), ",[180,1580,1500],{"class":190},[180,1582,194],{"class":186},[180,1584,645],{"class":190},[180,1586,1587],{"class":197},"()));\n",[180,1589,1590,1592,1595,1597,1599,1601,1603,1605,1607],{"class":182,"line":228},[180,1591,231],{"class":186},[180,1593,1594],{"class":197}," (lock, cvar) ",[180,1596,237],{"class":186},[180,1598,640],{"class":190},[180,1600,194],{"class":186},[180,1602,714],{"class":190},[180,1604,248],{"class":197},[180,1606,719],{"class":186},[180,1608,1609],{"class":197},"pair);\n",[180,1611,1612],{"class":182,"line":257},[180,1613,225],{"emptyLinePlaceholder":224},[180,1615,1616,1618,1620,1622,1624,1626,1628,1630,1632,1634],{"class":182,"line":281},[180,1617,231],{"class":186},[180,1619,813],{"class":197},[180,1621,237],{"class":186},[180,1623,240],{"class":190},[180,1625,194],{"class":186},[180,1627,245],{"class":190},[180,1629,248],{"class":197},[180,1631,517],{"class":186},[180,1633,520],{"class":186},[180,1635,254],{"class":197},[180,1637,1638,1640,1643,1646,1649,1651,1653,1655,1657,1659,1662,1664,1666,1668,1670,1673,1675,1677,1679,1681],{"class":182,"line":296},[180,1639,703],{"class":186},[180,1641,1642],{"class":197}," (",[180,1644,1645],{"class":186},"mut",[180,1647,1648],{"class":197}," started, cvar) ",[180,1650,237],{"class":186},[180,1652,1642],{"class":197},[180,1654,719],{"class":186},[180,1656,769],{"class":197},[180,1658,30],{"class":186},[180,1660,1661],{"class":269},"0.",[180,1663,769],{"class":190},[180,1665,418],{"class":197},[180,1667,30],{"class":186},[180,1669,423],{"class":190},[180,1671,1672],{"class":197},"(), ",[180,1674,719],{"class":186},[180,1676,769],{"class":197},[180,1678,30],{"class":186},[180,1680,485],{"class":269},[180,1682,293],{"class":197},[180,1684,1685,1688,1691],{"class":182,"line":324},[180,1686,1687],{"class":186},"    while",[180,1689,1690],{"class":186}," !*",[180,1692,1693],{"class":197},"started {\n",[180,1695,1696,1699,1701,1704,1706,1709,1712,1714,1716],{"class":182,"line":330},[180,1697,1698],{"class":197},"        started ",[180,1700,237],{"class":186},[180,1702,1703],{"class":197}," cvar",[180,1705,30],{"class":186},[180,1707,1708],{"class":190},"wait",[180,1710,1711],{"class":197},"(started)",[180,1713,30],{"class":186},[180,1715,423],{"class":190},[180,1717,426],{"class":197},[180,1719,1720],{"class":182,"line":336},[180,1721,327],{"class":197},[180,1723,1724],{"class":182,"line":341},[180,1725,333],{"class":197},[180,1727,1728],{"class":182,"line":359},[180,1729,225],{"emptyLinePlaceholder":224},[180,1731,1732],{"class":182,"line":372},[180,1733,1734],{"class":197},"{\n",[180,1736,1737,1739,1741,1743,1745,1747,1749,1751,1753,1755,1757,1759,1761,1763,1765,1767,1769,1771,1773,1775],{"class":182,"line":396},[180,1738,703],{"class":186},[180,1740,1642],{"class":197},[180,1742,1645],{"class":186},[180,1744,1648],{"class":197},[180,1746,237],{"class":186},[180,1748,1642],{"class":197},[180,1750,719],{"class":186},[180,1752,769],{"class":197},[180,1754,30],{"class":186},[180,1756,1661],{"class":269},[180,1758,769],{"class":190},[180,1760,418],{"class":197},[180,1762,30],{"class":186},[180,1764,423],{"class":190},[180,1766,1672],{"class":197},[180,1768,719],{"class":186},[180,1770,769],{"class":197},[180,1772,30],{"class":186},[180,1774,485],{"class":269},[180,1776,293],{"class":197},[180,1778,1779,1782,1785,1787,1790],{"class":182,"line":402},[180,1780,1781],{"class":186},"    *",[180,1783,1784],{"class":197},"started ",[180,1786,237],{"class":186},[180,1788,1789],{"class":269}," true",[180,1791,218],{"class":197},[180,1793,1794,1797,1799,1802],{"class":182,"line":407},[180,1795,1796],{"class":197},"    cvar",[180,1798,30],{"class":186},[180,1800,1801],{"class":190},"notify_one",[180,1803,426],{"class":197},[180,1805,1807],{"class":182,"line":1806},17,[180,1808,399],{"class":197},[180,1810,1812],{"class":182,"line":1811},18,[180,1813,225],{"emptyLinePlaceholder":224},[180,1815,1817,1819,1821,1823,1825,1827,1829],{"class":182,"line":1816},19,[180,1818,1187],{"class":197},[180,1820,30],{"class":186},[180,1822,415],{"class":190},[180,1824,418],{"class":197},[180,1826,30],{"class":186},[180,1828,423],{"class":190},[180,1830,426],{"class":197},[14,1832,1833,1834,1836],{},"The classic pattern: wait inside the lock; ",[23,1835,1708],{}," atomically releases + sleeps + reacquires.",[32,1838,1840],{"id":1839},"barrier",[23,1841,1504],{},[168,1843,1844],{"language":170},[172,1845,1847],{"className":174,"code":1846,"language":170,"meta":176,"style":176},"use std::sync::Barrier;\nlet barrier = Arc::new(Barrier::new(3));\n\u002F\u002F each thread calls barrier.wait(); all unblock once 3 reach it\n",[23,1848,1849,1865,1894],{"__ignoreMap":176},[180,1850,1851,1853,1855,1857,1859,1861,1863],{"class":182,"line":183},[180,1852,187],{"class":186},[180,1854,191],{"class":190},[180,1856,194],{"class":186},[180,1858,600],{"class":190},[180,1860,194],{"class":186},[180,1862,1504],{"class":190},[180,1864,218],{"class":197},[180,1866,1867,1869,1872,1874,1876,1878,1880,1882,1884,1886,1888,1890,1892],{"class":182,"line":201},[180,1868,231],{"class":186},[180,1870,1871],{"class":197}," barrier ",[180,1873,237],{"class":186},[180,1875,640],{"class":190},[180,1877,194],{"class":186},[180,1879,645],{"class":190},[180,1881,248],{"class":197},[180,1883,1504],{"class":190},[180,1885,194],{"class":186},[180,1887,645],{"class":190},[180,1889,248],{"class":197},[180,1891,495],{"class":269},[180,1893,321],{"class":197},[180,1895,1896],{"class":182,"line":221},[180,1897,1898],{"class":537},"\u002F\u002F each thread calls barrier.wait(); all unblock once 3 reach it\n",[32,1900,1902,26,1905],{"id":1901},"once-and-oncelock",[23,1903,1904],{},"Once",[23,1906,1907],{},"OnceLock",[168,1909,1910],{"language":170},[172,1911,1913],{"className":174,"code":1912,"language":170,"meta":176,"style":176},"use std::sync::OnceLock;\nstatic INIT: OnceLock\u003CVec\u003Cu8>> = OnceLock::new();\nlet data = INIT.get_or_init(|| load_config());\n",[23,1914,1915,1931,1969],{"__ignoreMap":176},[180,1916,1917,1919,1921,1923,1925,1927,1929],{"class":182,"line":183},[180,1918,187],{"class":186},[180,1920,191],{"class":190},[180,1922,194],{"class":186},[180,1924,600],{"class":190},[180,1926,194],{"class":186},[180,1928,1907],{"class":190},[180,1930,218],{"class":197},[180,1932,1933,1936,1939,1942,1945,1948,1951,1953,1956,1959,1961,1963,1965,1967],{"class":182,"line":201},[180,1934,1935],{"class":186},"static",[180,1937,1938],{"class":269}," INIT",[180,1940,1941],{"class":186},":",[180,1943,1944],{"class":190}," OnceLock",[180,1946,1947],{"class":197},"\u003C",[180,1949,1950],{"class":190},"Vec",[180,1952,1947],{"class":197},[180,1954,1955],{"class":190},"u8",[180,1957,1958],{"class":197},">> ",[180,1960,237],{"class":186},[180,1962,1944],{"class":190},[180,1964,194],{"class":186},[180,1966,645],{"class":190},[180,1968,426],{"class":197},[180,1970,1971,1973,1975,1977,1979,1981,1984,1986,1988,1991],{"class":182,"line":221},[180,1972,231],{"class":186},[180,1974,474],{"class":197},[180,1976,237],{"class":186},[180,1978,1938],{"class":269},[180,1980,30],{"class":186},[180,1982,1983],{"class":190},"get_or_init",[180,1985,248],{"class":197},[180,1987,251],{"class":186},[180,1989,1990],{"class":190}," load_config",[180,1992,1281],{"class":197},[32,1994,1996],{"id":1995},"atomic-types","Atomic Types",[14,1998,1999,52,2002,82,2005,82,2008,82,2011,2014],{},[23,2000,2001],{},"std::sync::atomic",[23,2003,2004],{},"AtomicBool",[23,2006,2007],{},"AtomicI32",[23,2009,2010],{},"AtomicUsize",[23,2012,2013],{},"AtomicPtr\u003CT>",", etc.",[168,2016,2017],{"language":170},[172,2018,2020],{"className":174,"code":2019,"language":170,"meta":176,"style":176},"use std::sync::atomic::{AtomicUsize, Ordering};\nlet n = AtomicUsize::new(0);\nn.fetch_add(1, Ordering::SeqCst);\nn.compare_exchange(0, 1, Ordering::SeqCst, Ordering::Relaxed);\n",[23,2021,2022,2050,2071,2096],{"__ignoreMap":176},[180,2023,2024,2026,2028,2030,2032,2034,2037,2039,2041,2043,2045,2048],{"class":182,"line":183},[180,2025,187],{"class":186},[180,2027,191],{"class":190},[180,2029,194],{"class":186},[180,2031,600],{"class":190},[180,2033,194],{"class":186},[180,2035,2036],{"class":190},"atomic",[180,2038,194],{"class":186},[180,2040,605],{"class":197},[180,2042,2010],{"class":190},[180,2044,82],{"class":197},[180,2046,2047],{"class":190},"Ordering",[180,2049,614],{"class":197},[180,2051,2052,2054,2056,2058,2061,2063,2065,2067,2069],{"class":182,"line":201},[180,2053,231],{"class":186},[180,2055,759],{"class":197},[180,2057,237],{"class":186},[180,2059,2060],{"class":190}," AtomicUsize",[180,2062,194],{"class":186},[180,2064,645],{"class":190},[180,2066,248],{"class":197},[180,2068,658],{"class":269},[180,2070,293],{"class":197},[180,2072,2073,2076,2078,2081,2083,2085,2087,2089,2091,2094],{"class":182,"line":221},[180,2074,2075],{"class":197},"n",[180,2077,30],{"class":186},[180,2079,2080],{"class":190},"fetch_add",[180,2082,248],{"class":197},[180,2084,485],{"class":269},[180,2086,82],{"class":197},[180,2088,2047],{"class":190},[180,2090,194],{"class":186},[180,2092,2093],{"class":190},"SeqCst",[180,2095,293],{"class":197},[180,2097,2098,2100,2102,2105,2107,2109,2111,2113,2115,2117,2119,2121,2123,2125,2127,2130],{"class":182,"line":228},[180,2099,2075],{"class":197},[180,2101,30],{"class":186},[180,2103,2104],{"class":190},"compare_exchange",[180,2106,248],{"class":197},[180,2108,658],{"class":269},[180,2110,82],{"class":197},[180,2112,485],{"class":269},[180,2114,82],{"class":197},[180,2116,2047],{"class":190},[180,2118,194],{"class":186},[180,2120,2093],{"class":190},[180,2122,82],{"class":197},[180,2124,2047],{"class":190},[180,2126,194],{"class":186},[180,2128,2129],{"class":190},"Relaxed",[180,2131,293],{"class":197},[1201,2133,2135],{"id":2134},"orderings","Orderings",[40,2137,2138,2143,2152,2160,2166],{},[43,2139,2140,2142],{},[23,2141,2129],{},": no ordering constraints, just atomicity.",[43,2144,2145,2148,2149,162],{},[23,2146,2147],{},"Acquire",": later reads see the latest writes (pair with ",[23,2150,2151],{},"Release",[43,2153,2154,2156,2157,2159],{},[23,2155,2151],{},": prior writes are visible to ",[23,2158,2147],{}," readers.",[43,2161,2162,2165],{},[23,2163,2164],{},"AcqRel",": both.",[43,2167,2168,2170],{},[23,2169,2093],{},": total order across threads (most expensive).",[14,2172,2173,2174,2176,2177,69,2179,69,2181,2183],{},"Use ",[23,2175,2093],{}," if unsure; switch to ",[23,2178,2129],{},[23,2180,2147],{},[23,2182,2151],{}," once you understand the memory model.",[32,2185,2187],{"id":2186},"thread-local-storage","Thread-Local Storage",[168,2189,2190],{"language":170},[172,2191,2193],{"className":174,"code":2192,"language":170,"meta":176,"style":176},"use std::cell::RefCell;\nthread_local! {\n    static COUNTER: RefCell\u003Cu32> = RefCell::new(0);\n}\n\nCOUNTER.with(|c| { *c.borrow_mut() += 1; });\n",[23,2194,2195,2213,2220,2255,2259,2263],{"__ignoreMap":176},[180,2196,2197,2199,2201,2203,2206,2208,2211],{"class":182,"line":183},[180,2198,187],{"class":186},[180,2200,191],{"class":190},[180,2202,194],{"class":186},[180,2204,2205],{"class":190},"cell",[180,2207,194],{"class":186},[180,2209,2210],{"class":190},"RefCell",[180,2212,218],{"class":197},[180,2214,2215,2218],{"class":182,"line":201},[180,2216,2217],{"class":190},"thread_local!",[180,2219,254],{"class":197},[180,2221,2222,2225,2228,2230,2233,2235,2238,2241,2243,2245,2247,2249,2251,2253],{"class":182,"line":221},[180,2223,2224],{"class":186},"    static",[180,2226,2227],{"class":269}," COUNTER",[180,2229,1941],{"class":186},[180,2231,2232],{"class":190}," RefCell",[180,2234,1947],{"class":197},[180,2236,2237],{"class":190},"u32",[180,2239,2240],{"class":197},"> ",[180,2242,237],{"class":186},[180,2244,2232],{"class":190},[180,2246,194],{"class":186},[180,2248,645],{"class":190},[180,2250,248],{"class":197},[180,2252,658],{"class":269},[180,2254,293],{"class":197},[180,2256,2257],{"class":182,"line":228},[180,2258,399],{"class":197},[180,2260,2261],{"class":182,"line":257},[180,2262,225],{"emptyLinePlaceholder":224},[180,2264,2265,2268,2270,2273,2275,2278,2281,2283,2286,2288,2290,2292,2295,2298,2300,2302],{"class":182,"line":281},[180,2266,2267],{"class":269},"COUNTER",[180,2269,30],{"class":186},[180,2271,2272],{"class":190},"with",[180,2274,248],{"class":197},[180,2276,2277],{"class":186},"|",[180,2279,2280],{"class":197},"c",[180,2282,2277],{"class":186},[180,2284,2285],{"class":197}," { ",[180,2287,1014],{"class":186},[180,2289,2280],{"class":197},[180,2291,30],{"class":186},[180,2293,2294],{"class":190},"borrow_mut",[180,2296,2297],{"class":197},"() ",[180,2299,788],{"class":186},[180,2301,791],{"class":269},[180,2303,2304],{"class":197},"; });\n",[14,2306,2307],{},"Per-thread state, no synchronization needed.",[32,2309,2311],{"id":2310},"async-vs-threads","Async vs Threads",[40,2313,2314,2320],{},[43,2315,2316,2319],{},[18,2317,2318],{},"Threads",": OS-level, ~1 MB stack, ~few µs context switch. Good for blocking I\u002FO.",[43,2321,2322,2325],{},[18,2323,2324],{},"Async",": lightweight tasks, ~few KB stack, runtime-driven. Good for many concurrent I\u002FO-bound tasks.",[14,2327,2328,2329,2332,2333,69,2336,2339],{},"For CPU-bound work, threads or ",[23,2330,2331],{},"rayon"," (data parallelism) are appropriate. For many concurrent I\u002FO operations, async (",[23,2334,2335],{},"tokio",[23,2337,2338],{},"async-std",") scales better.",[32,2341,2343,2345],{"id":2342},"rayon-for-data-parallelism",[23,2344,2331],{}," for Data Parallelism",[168,2347,2348],{"language":170},[172,2349,2351],{"className":174,"code":2350,"language":170,"meta":176,"style":176},"use rayon::prelude::*;\nlet v: Vec\u003Ci32> = (1..=100).collect();\nlet sum: i32 = v.par_iter().map(|x| x * 2).sum();\n",[23,2352,2353,2370,2409],{"__ignoreMap":176},[180,2354,2355,2357,2360,2362,2365,2368],{"class":182,"line":183},[180,2356,187],{"class":186},[180,2358,2359],{"class":190}," rayon",[180,2361,194],{"class":186},[180,2363,2364],{"class":190},"prelude",[180,2366,2367],{"class":186},"::*",[180,2369,218],{"class":197},[180,2371,2372,2374,2377,2379,2382,2384,2386,2388,2390,2392,2394,2397,2400,2402,2404,2407],{"class":182,"line":201},[180,2373,231],{"class":186},[180,2375,2376],{"class":197}," v",[180,2378,1941],{"class":186},[180,2380,2381],{"class":190}," Vec",[180,2383,1947],{"class":197},[180,2385,81],{"class":190},[180,2387,2240],{"class":197},[180,2389,237],{"class":186},[180,2391,1642],{"class":197},[180,2393,485],{"class":269},[180,2395,2396],{"class":186},"..=",[180,2398,2399],{"class":269},"100",[180,2401,1176],{"class":197},[180,2403,30],{"class":186},[180,2405,2406],{"class":190},"collect",[180,2408,426],{"class":197},[180,2410,2411,2413,2416,2418,2421,2424,2426,2428,2431,2433,2435,2438,2440,2442,2445,2447,2450,2452,2455,2457,2459,2462],{"class":182,"line":221},[180,2412,231],{"class":186},[180,2414,2415],{"class":197}," sum",[180,2417,1941],{"class":186},[180,2419,2420],{"class":190}," i32",[180,2422,2423],{"class":186}," =",[180,2425,2376],{"class":197},[180,2427,30],{"class":186},[180,2429,2430],{"class":190},"par_iter",[180,2432,418],{"class":197},[180,2434,30],{"class":186},[180,2436,2437],{"class":190},"map",[180,2439,248],{"class":197},[180,2441,2277],{"class":186},[180,2443,2444],{"class":197},"x",[180,2446,2277],{"class":186},[180,2448,2449],{"class":197}," x ",[180,2451,1014],{"class":186},[180,2453,2454],{"class":269}," 2",[180,2456,1176],{"class":197},[180,2458,30],{"class":186},[180,2460,2461],{"class":190},"sum",[180,2463,426],{"class":197},[14,2465,2466,2469],{},[23,2467,2468],{},"par_iter()"," runs the iteration across a thread pool. Drop-in replacement for sequential iterators in many cases.",[32,2471,2473],{"id":2472},"common-pitfalls","Common Pitfalls",[40,2475,2476,2482,2493,2513,2519,2527,2540,2546,2554,2560],{},[43,2477,2478,2481],{},[18,2479,2480],{},"Deadlock",": inconsistent lock ordering. Acquire locks in a fixed global order, or use a single lock.",[43,2483,2484,2490,2491,30],{},[18,2485,2486,2489],{},[23,2487,2488],{},"Rc"," across threads",": compile error. Use ",[23,2492,578],{},[43,2494,2495,2501,2502,2505,2506,2509,2510,30],{},[18,2496,2497,2498],{},"Holding a lock across ",[23,2499,2500],{},"await",": in async code, this can deadlock; use ",[23,2503,2504],{},"tokio::sync::Mutex"," instead of ",[23,2507,2508],{},"std::sync::Mutex"," for async contexts, or ",[23,2511,2512],{},"spawn_blocking",[43,2514,2515,2518],{},[18,2516,2517],{},"Lock poisoning",": if a thread panics while holding a lock, the lock becomes poisoned. Decide on a recovery policy.",[43,2520,2521,2526],{},[18,2522,2523,2524],{},"Spawning without ",[23,2525,415],{},": detached threads can outlive main, dropping work mid-flight. Detach deliberately, not by accident.",[43,2528,2529,2536,2537,2539],{},[18,2530,2531,2533,2534],{},[23,2532,433],{}," requires ",[23,2535,571],{},": closures can't borrow stack data unless ",[23,2538,517],{},"d.",[43,2541,2542,2545],{},[18,2543,2544],{},"Shared mutable state",": prefer message passing (channels) when possible — it isolates state and avoids locking.",[43,2547,2548,2553],{},[18,2549,2550,2552],{},[23,2551,91],{}," are not enough for correctness",": they prevent data races, not logical races or deadlocks.",[43,2555,2556,2559],{},[18,2557,2558],{},"Atomic orderings are subtle",": wrong ordering causes bugs that don't show on x86 (which is strongly ordered). Test on weak architectures (ARM).",[43,2561,2562,2571,2572,2574],{},[18,2563,2564,2567,2568],{},[23,2565,2566],{},"Mutex::lock()"," returns ",[23,2569,2570],{},"Result",": poison is the failure mode. Don't ",[23,2573,423],{}," blindly in production code paths.",[32,2576,2578],{"id":2577},"patterns","Patterns",[40,2580,2581,2590,2602,2612,2625],{},[43,2582,2583,52,2586,2589],{},[18,2584,2585],{},"Work queue",[23,2587,2588],{},"mpsc"," channels + worker pool.",[43,2591,2592,52,2595,69,2598,2601],{},[18,2593,2594],{},"Pub-Sub",[23,2596,2597],{},"async-channel",[23,2599,2600],{},"tokio::sync::broadcast"," for multiple receivers.",[43,2603,2604,2607,2608,2611],{},[18,2605,2606],{},"Producer-consumer",": bounded ",[23,2609,2610],{},"sync_channel"," for backpressure.",[43,2613,2614,52,2617,2620,2621,2624],{},[18,2615,2616],{},"Read-mostly cache",[23,2618,2619],{},"RwLock\u003CHashMap\u003C...>>"," or ",[23,2622,2623],{},"arc-swap"," for atomic replacement.",[43,2626,2627,2630],{},[18,2628,2629],{},"Sharded locks",": split data into N shards each with its own lock (reduces contention).",[32,2632,2634],{"id":2633},"thread-pool","Thread Pool",[14,2636,2637,2640,2641,2643,2644,2646,2647,69,2650,2653],{},[23,2638,2639],{},"std::thread"," doesn't have a built-in pool. Use ",[23,2642,2331],{}," (data parallel), ",[23,2645,2335],{}," (async), or ",[23,2648,2649],{},"threadpool",[23,2651,2652],{},"crossbeam_pool"," (custom).",[32,2655,2657],{"id":2656},"summary","Summary",[14,2659,2660,69,2662,2664,2665,2667,2668,69,2670,2672,2673,69,2675,69,2677,2679,2680,2682],{},[23,2661,25],{},[23,2663,29],{}," are the foundation. Use ",[23,2666,578],{}," for shared ownership, ",[23,2669,582],{},[23,2671,860],{}," for synchronization, channels for message passing. Atomics for low-level coordination. ",[23,2674,1500],{},[23,2676,1504],{},[23,2678,1907],{}," for common patterns. ",[23,2681,2331],{}," for data parallelism. Prefer async for I\u002FO-bound concurrency.",[14,2684,2685],{},"Next: Async\u002Fawait — the modern Rust concurrency story.",[2687,2688,2689],"style",{},"html pre.shiki code .svdQ7, html code.shiki .svdQ7{--shiki-default:#D73A49;--shiki-github-dark:#F97583}html pre.shiki code .sIsaT, html code.shiki .sIsaT{--shiki-default:#6F42C1;--shiki-github-dark:#B392F0}html pre.shiki code .ssxIu, html code.shiki .ssxIu{--shiki-default:#24292E;--shiki-github-dark:#E1E4E8}html pre.shiki code .snvgF, html code.shiki .snvgF{--shiki-default:#005CC5;--shiki-github-dark:#79B8FF}html pre.shiki code .sJ6F3, html code.shiki .sJ6F3{--shiki-default:#032F62;--shiki-github-dark:#9ECBFF}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 .github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html.github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html pre.shiki code .sdCPZ, html code.shiki .sdCPZ{--shiki-default:#6A737D;--shiki-github-dark:#6A737D}",{"title":176,"searchDepth":201,"depth":201,"links":2691},[2692,2694,2695,2696,2698,2700,2705,2707,2708,2709,2711,2714,2715,2716,2718,2719,2720,2721],{"id":34,"depth":201,"text":2693},"Send and Sync",{"id":165,"depth":201,"text":166},{"id":459,"depth":201,"text":460},{"id":574,"depth":201,"text":2697},"Shared State with Arc + Mutex",{"id":857,"depth":201,"text":2699},"RwLock for Read-Heavy Workloads",{"id":1026,"depth":201,"text":1027,"children":2701},[2702,2703,2704],{"id":1203,"depth":221,"text":1204},{"id":1317,"depth":221,"text":1318},{"id":1341,"depth":221,"text":1342},{"id":1401,"depth":201,"text":2706},"park and unpark",{"id":1507,"depth":201,"text":1500},{"id":1839,"depth":201,"text":1504},{"id":1901,"depth":201,"text":2710},"Once and OnceLock",{"id":1995,"depth":201,"text":1996,"children":2712},[2713],{"id":2134,"depth":221,"text":2135},{"id":2186,"depth":201,"text":2187},{"id":2310,"depth":201,"text":2311},{"id":2342,"depth":201,"text":2717},"rayon for Data Parallelism",{"id":2472,"depth":201,"text":2473},{"id":2577,"depth":201,"text":2578},{"id":2633,"depth":201,"text":2634},{"id":2656,"depth":201,"text":2657},"Rust's promise: fearless concurrency. The type system prevents data races at compile time via Send and Sync.","md",{},"\u002Frust\u002F22-concurrency",{"title":5,"description":2722},"rust\u002F22-concurrency","ZxAq8a5E9lzbMEjR95Zl4NoC1Z_87w4h-2GLmzwg1M0",1785944093259]