## Linux 核心專題: POSIX Thread 相容實作 > 執行人: LULser0204 > [專題解說影片](https://youtu.be/cB5UyDOsvfo) ### Reviewed by `cheezad` 第一段有一個小錯字 (exameple),已修正 > 謝謝 ### Reviewed by `eleanorLYJ` 需要更多的初步介紹讓人能更快看懂你要做甚麼,例如第一個 todo,實驗目的為何?還有 MutexShootout 專案的目的是什麼?雖然你影片有用一句話說明,但仍建議可以增加敘述。 >好的 ## 任務簡介 建立 POSIX Thread 部分相容且輕量級的實作。 ## TODO: 研讀[實作輕量級的 Mutex Lock](/@sysprog/concurrency-mutex)和[建立 PThread 相容實作](/@sysprog/concurrency-thread-package) > 重現實驗並紀錄問題 :::info 該實驗主要是比較 pthread 和 futex 的表現,其中 pthread 的部分使用 skinny_mutex 來實作 ::: > [實作輕量級的 Mutex Lock](/@sysprog/concurrency-mutex) >其中 futex 是放在 [perf-test/main.c](https://github.com/sysprog21/concurrent-programs/blob/master/mutex/perf-test/main.c) 的程式碼,pthread 則是 結合了 [skinny_mutex](https://github.com/jserv/skinny-mutex) 也可稱作 Low-memory-footprint mutexes for pthreads :::danger 闡述 [skinny_mutex](https://github.com/jserv/skinny-mutex) 要解決什麼問題,以及何以稱為「輕量級」。 >skinny_mutex 目的是在不犧牲效能的前提下,減少佔用的記憶體空間。用於取代 pthread api 提供的 mutex,特別是當 mutex 保護的是小型資料結構。 > 為何稱為「輕量級」呢? 因為標準的 pthread_mutex_t 佔用的記憶體空間( 24bytes on 32-bit machine and 40bytes on 64-bit machines )較多;而 skinny_mutex 只佔用一個指標大小的空間 ::: 一開始我嘗試在 [example](https://github.com/sysprog21/concurrent-programs/blob/master/mutex/example/main.c) 的makefile 跳出 ``` Running test_pthread … FATAL: ThreadSanitizer: unexpected memory mapping 0x5c0c629fb000-0x5c0c629fc000 Running test_linux … FATAL: ThreadSanitizer: unexpected memory mapping 0x5ea429899000-0x5ea42989a000 make: *** [Makefile:27: check] Error 66 ``` 這個問題是 ThreadSanitizer (TSan) 出現了意外的記憶體映射。 參考 [ThreadSanitizer: unexpected memory mapping](https://github.com/google/sanitizers/issues/806),我一開始認為是我的 GCC 版本問題,但更新後還是碰到相同的問題。後來查到 [FATAL: ThreadSanitizer: unexpected memory mapping when running on Linux Kernels 6.6+](https://stackoverflow.com/questions/77850769/fatal-threadsanitizer-unexpected-memory-mapping-when-running-on-linux-kernels) 的討論,只要執行 `sudo sysctl vm.mmap_rnd_bits=28` 就可以正確執行了。 因為 ThreadSanitizer 需要對程式的記憶體操作進行精確的追蹤和檢測。如果記憶體地址的隨機化程度太高,可能會導致 ThreadSanitizer 無法正確預測和管理記憶體映射,通過 `vm.mmap_rnd_bits=28` 減少了地址的隨機性。 可以觀察到 futex 大多時候表現優於 pthread 的實作 ![Q8ebId7 - Imgur](https://hackmd.io/_uploads/B1W3nk7IA.png) > [建立 PThread 相容實作](/@sysprog/concurrency-thread-package) :::info 該實驗主要是測試解決 Priority Inversion 的不同方法。 先使用 Normal mutex 重現 Priority Inversion,分別是用 Priority Inheritance mutex、Priority Protection mutex 來解決 > Priority Inheritance mutex :假設低優先權的 thread 先取得 lock,當高優先權的 thread 想要取得 lock 時,發現 lock 已被低優先權的持有,此時高優先權的 thread 會讓目前持有 lock 的 thread 先暫時提高優先權,等待其釋放 lock 後再將優先權降回原本 > Priority Protection mutex :每個 mutex 建立時都會被賦予一個 prioceiling 的值(比所有可能獲得該 mutex thread 優先權都還要高的值)。當 thread 取得 lock 時,該優先權會被提升到 prioceiling ,確保不會被低優先權搶佔 ; 另一個實作方式是 當 thread 取得 mutex 時,將持有 mutex 的 thread 提高到該排程策略的最高優先級,只是可能會過度提升,導致其他執行重要任務的 thread 無法使用 CPU 資源 ::: 我在執行 [建立 PThread 相容實作](https://hackmd.io/@sysprog/concurrency-thread-package) 內 [測試程式](https://github.com/sysprog21/MuThread/tree/main/Tests) 時,在我輸入 `make test` 後,總是回報 `segmentation fault` ,我有嘗試將程式內 muprint 部分改成 pthread 仍然有相同的問題。於是我嘗試用 gdb 觀察是斷在什麼地方,設定了三個 break point (在 thread_func_normal、thread_func_recursive、main ) ,除了第一條 thread 能夠正確執行 `muthread_t self = muthread_self()`外,其他幾條執行都會觸發錯誤。 另外我也有修改 makefile 觀察是否只有 test01 有這問題,然而只有部分幾個能正常執行。 - [ ] GDB 除錯訊息 ``` (gdb) n [New Thread 0x55555555c010 (LWP 113324)] [Switching to Thread 0x55555555c010 (LWP 113324)] Thread 2 "test-01-basic" hit Breakpoint 2, thread_func_normal (arg=0x7fffffffdec0) at Tests/test-01-basic.c:9 9 muthread_t self = muthread_self(); (gdb) info thread Id Target Id Frame 1 Thread 0x7ffff7fa0740 (LWP 113321) "test-01-basic" main (argc=1, argv=0x7fffffffe058) at Tests/test-01-basic.c:113 * 2 Thread 0x55555555c010 (LWP 113324) "test-01-basic" thread_func_normal (arg=0x7fffffffdec0) at Tests/test-01-basic.c:9 (gdb) thread 2 [Switching to thread 2 (Thread 0x55555555c010 (LWP 113324))] #0 thread_func_normal (arg=0x7fffffffdec0) at Tests/test-01-basic.c:9 9 muthread_t self = muthread_self(); (gdb) n [New Thread 0x55555555c1e8 (LWP 113325)] [New Thread 0x55555555c3c0 (LWP 113326)] [New Thread 0x55555555c598 (LWP 113327)] [Switching to Thread 0x55555555c1e8 (LWP 113325)] Thread 3 "test-01-basic" hit Breakpoint 2, thread_func_normal (arg=0x7fffffffdec0) at Tests/test-01-basic.c:9 9 muthread_t self = muthread_self(); (gdb) info thread Id Target Id Frame 1 Thread 0x7ffff7fa0740 (LWP 113321) "test-01-basic" muclone () at clone.S:65 2 Thread 0x55555555c010 (LWP 113324) "test-01-basic" 0x00005555555551fa in thread_func_normal (arg=0x7fffffffdec0) at Tests/test-01-basic.c:9 * 3 Thread 0x55555555c1e8 (LWP 113325) "test-01-basic" thread_func_normal (arg=0x7fffffffdec0) at Tests/test-01-basic.c:9 4 Thread 0x55555555c3c0 (LWP 113326) "test-01-basic" thread_func_normal (arg=0x7fffffffdec0) at Tests/test-01-basic.c:9 5 Thread 0x55555555c598 (LWP 113327) "test-01-basic" muclone () at clone.S:65 (gdb) n thread_get_info_callback: cannot get thread info: generic error (gdb) Thread 1 "test-01-basic" stopped. [Switching to Thread 0x7ffff7fa0740 (LWP 113321)] muclone () at clone.S:65 65 testq %rax, %rax // compare %rax && %rax to zero n Fatal signal: Segmentation fault ----- Backtrace ----- 0x561565196077 ??? 0x561565298859 ??? 0x561565298a22 ??? 0x7e8137e4251f ??? ./signal/../sysdeps/unix/sysv/linux/x86_64/libc_sigaction.c:0 0x56156534288a ??? 0x561565343e1f ??? 0x5615654b34bf ??? 0x5615653066a0 ??? 0x56156530fc42 ??? 0x561565311660 ??? 0x56156564a815 ??? 0x56156564acf9 ??? 0x56156535636c ??? 0x561565358054 ??? 0x5615650ee15f ??? 0x7e8137e29d8f __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58 0x7e8137e29e3f __libc_start_main_impl ../csu/libc-start.c:392 0x5615650f3bf4 ??? 0xffffffffffffffff ??? ``` - [ ] 嘗試執行所有 test ``` $ make check Running test-01-basic... [thread main] Testing normal mutex Segmentation fault (core dumped) Running test-02-multiple-type... [thread main] Testing normal mutex fail to set scheduler Failed to spawn thread 0: Operation not permitted Segmentation fault (core dumped) Running test-03-add-count... count = 2000000 Running test-04-priority-inversion... fail to set scheduler Failed to spawn thread 2: Segmentation fault (core dumped) Running test-05-priority-inversion-PI... fail to set scheduler Failed to spawn thread 2: Operation not permitted Running test-06-priority-inversion-PP... fail to set scheduler Failed to spawn thread 2: Operation not permitted Segmentation fault (core dumped) Running test-07-benchmark... Usage: lock_test [-t nThreads=1] [-n size=1000000] [-m repeat=100] [-l lockType=1] Lock type: 0 for mutex; Hash: 0 (should be 0 if -m is even or aaaaaaaaaaaaaaa if -m is odd) time = 2497110528 Running test-08-benchmark-PI... fail to set scheduler fail to set scheduler fail to set scheduler fail to set scheduler fail to set scheduler fail to set scheduler fail to set scheduler fail to set scheduler fail to set scheduler fail to set scheduler Running test-09-benchmark-PP... fail to set scheduler Segmentation fault (core dumped) Running test-10-condvar-signal... Segmentation fault (core dumped) Running test-11-condvar-signal_pi... fail to set scheduler fail to set scheduler fail to set scheduler fail to set scheduler fail to set scheduler fail to set scheduler fail to set scheduler fail to set scheduler Segmentation fault (core dumped) Running test-12-prio-wake... sched parameter or policy is NULL Segmentation fault (core dumped) ``` 我後來在另一台電腦,Linux 系統資訊 : ``` $ lsb_release -d Description: Ubuntu 20.04.6 LTS $ uname -r 5.15.0-107-generic ``` 可以正常的執行,我觀察兩個 GDB 執行狀況,在 20.04 版本跑得會顯示 "Trying to acquire the mutex succeeded" ``` (gdb) continue Continuing. [New Thread 0x55555555c3c0 (LWP 1198575)] [New Thread 0x55555555c598 (LWP 1198576)] [Switching to Thread 0x55555555c1e8 (LWP 1198569)] Thread 3 "test-01-basic" hit Breakpoint 1, thread_func_normal (arg=0x0) at Tests/test-01-basic.c:8 8 { (gdb) info thread Id Target Id Frame 1 Thread 0x7ffff7d96740 (LWP 1198564) "test-01-basic" muclone () at clone.S:65 2 Thread 0x55555555c010 (LWP 1198568) "test-01-basic" 0x00005555555551e4 in thread_func_normal (arg=0x0) at Tests/test-01-basic.c:8 * 3 Thread 0x55555555c1e8 (LWP 1198569) "test-01-basic" thread_func_normal (arg=0x0) at Tests/test-01-basic.c:8 4 Thread 0x55555555c3c0 (LWP 1198575) "test-01-basic" thread_func_normal (arg=0x0) at Tests/test-01-basic.c:8 5 Thread 0x55555555c598 (LWP 1198576) "test-01-basic" muclone () at clone.S:65 (gdb) continue Continuing. [thread 0x55555555c010] Trying to acquire the mutex succeeded [thread 0x55555555c010] Starting normal mutex test ``` 另外我使用 Valgrind 分別對 ubuntu 20.04 和 ubuntu 22.04 觀察 Segmentation fault 原因,此為 ubuntu 22.04 ``` $ valgrind ./test-01-basic ==8373== Memcheck, a memory error detector ==8373== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==8373== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info ==8373== Command: ./test-01-basic ==8373== [thread main] Testing normal mutex ==8373== Conditional jump or move depends on uninitialised value(s) ==8373== at 0x10B159: muthread_create (thread.c:130) ==8373== by 0x109654: main (test-01-basic.c:111) ==8373== [thread main] Threads spawned successfully ==8373== Thread 5: ==8373== Invalid read of size 1 ==8373== at 0x49069FF: __pthread_enable_asynccancel (cancellation.c:34) ==8373== by 0x498A8A6: __libc_write (write.c:26) ==8373== by 0x498A8A6: write (write.c:24) ==8373== by 0x10B445: muwrite (util.c:39) ==8373== by 0x10B76E: muprint (util.c:103) ==8373== by 0x109247: thread_func_normal (test-01-basic.c:13) ==8373== by 0x10AF05: start_thread (thread.c:55) ==8373== by 0x10C141: ??? (clone.S:78) ==8373== Address 0x52a2fe2 is 1,362 bytes inside an unallocated block of size 4,191,568 in arena "client" ==8373== ==8373== Invalid write of size 1 ==8373== at 0x4906A0A: __pthread_enable_asynccancel (cancellation.c:35) ==8373== by 0x498A8A6: __libc_write (write.c:26) ==8373== by 0x498A8A6: write (write.c:24) ==8373== by 0x10B445: muwrite (util.c:39) ==8373== by 0x10B76E: muprint (util.c:103) ==8373== by 0x109247: thread_func_normal (test-01-basic.c:13) ==8373== by 0x10AF05: start_thread (thread.c:55) ==8373== by 0x10C141: ??? (clone.S:78) ==8373== Address 0x52a2fe2 is 1,362 bytes inside an unallocated block of size 4,191,568 in arena "client" ==8373== ==8373== Invalid read of size 1 ==8373== at 0x4906A1B: __pthread_enable_asynccancel (cancellation.c:39) ==8373== by 0x498A8A6: __libc_write (write.c:26) ==8373== by 0x498A8A6: write (write.c:24) ==8373== by 0x10B445: muwrite (util.c:39) ==8373== by 0x10B76E: muprint (util.c:103) ==8373== by 0x109247: thread_func_normal (test-01-basic.c:13) ==8373== by 0x10AF05: start_thread (thread.c:55) ==8373== by 0x10C141: ??? (clone.S:78) ==8373== Address 0x800971 is not stack'd, malloc'd or (recently) free'd ==8373== ==8373== ==8373== Process terminating with default action of signal 11 (SIGSEGV) ==8373== Access not within mapped region at address 0x800971 ==8373== at 0x4906A1B: __pthread_enable_asynccancel (cancellation.c:39) ==8373== by 0x498A8A6: __libc_write (write.c:26) ==8373== by 0x498A8A6: write (write.c:24) ==8373== by 0x10B445: muwrite (util.c:39) ==8373== by 0x10B76E: muprint (util.c:103) ==8373== by 0x109247: thread_func_normal (test-01-basic.c:13) ==8373== by 0x10AF05: start_thread (thread.c:55) ==8373== by 0x10C141: ??? (clone.S:78) ==8373== If you believe this happened as a result of a stack ==8373== overflow in your program's main thread (unlikely but ==8373== possible), you can try to increase the size of the ==8373== main thread stack using the --main-stacksize= flag. ==8373== The main thread stack size used in this run was 8388608. ==8373== ==8373== HEAP SUMMARY: ==8373== in use at exit: 2,280 bytes in 5 blocks ==8373== total heap usage: 5 allocs, 0 frees, 2,280 bytes allocated ==8373== ==8373== LEAK SUMMARY: ==8373== definitely lost: 0 bytes in 0 blocks ==8373== indirectly lost: 0 bytes in 0 blocks ==8373== possibly lost: 0 bytes in 0 blocks ==8373== still reachable: 2,280 bytes in 5 blocks ==8373== suppressed: 0 bytes in 0 blocks ==8373== Rerun with --leak-check=full to see details of leaked memory ==8373== ==8373== Use --track-origins=yes to see where uninitialised values come from ==8373== For lists of detected and suppressed errors, rerun with: -s ==8373== ERROR SUMMARY: 8 errors from 4 contexts (suppressed: 0 from 0) Segmentation fault (core dumped) ``` 此為 ubuntu 20.04 ,該環境也有 invalid read of size 只是在 22.04 的 size 大小是 1 ,20.04 size 大小是 4 (節錄部分,可以完全執行) ``` ne6121157@vision-Z790-AORUS-ELITE-AX-ICE:~/MuThread$ valgrind ./test-01-basic ==1199494== Memcheck, a memory error detector ==1199494== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==1199494== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info ==1199494== Command: ./test-01-basic ==1199494== [thread main] Testing normal mutex ==1199494== Conditional jump or move depends on uninitialised value(s) ==1199494== at 0x10B0D5: muthread_create (thread.c:130) ==1199494== by 0x109615: main (test-01-basic.c:111) ==1199494== [thread main] Threads spawned successfully [thread 0x527b250] Trying to acquire the mutex succeeded [thread 0x527b250] Starting normal mutex test ==1199494== Thread 6: ==1199494== Invalid read of size 4 ==1199494== at 0x4876044: __pthread_enable_asynccancel (cancellation.S:48) ==1199494== by 0x4876316: __libc_write (write.c:26) ==1199494== by 0x4876316: write (write.c:24) ==1199494== by 0x10B3B5: muwrite (util.c:38) ==1199494== by 0x10B6DB: muprint (util.c:102) ==1199494== by 0x109255: thread_func_normal (test-01-basic.c:17) ==1199494== by 0x10AE81: start_thread (thread.c:55) ==1199494== by 0x10C071: ??? (clone.S:78) ==1199494== Address 0x527bb88 is 248 bytes inside an unallocated block of size 4,191,568 in arena "client" ==1199494== ==1199494== Invalid read of size 4 ==1199494== at 0x4876058: __pthread_enable_asynccancel (cancellation.S:54) ==1199494== by 0x4876316: __libc_write (write.c:26) ==1199494== by 0x4876316: write (write.c:24) ==1199494== by 0x10B3B5: muwrite (util.c:38) ==1199494== by 0x10B6DB: muprint (util.c:102) ==1199494== by 0x109255: thread_func_normal (test-01-basic.c:17) ==1199494== by 0x10AE81: start_thread (thread.c:55) ==1199494== by 0x10C071: ??? (clone.S:78) ==1199494== Address 0x527bb88 is 248 bytes inside an unallocated block of size 4,191,568 in arena "client" ==1199494== ``` 最後實驗結果 (只擷取部分) [ priority-inversion、priority-inversion-PI、priority-inversion-PP ] ``` count = 2000000 +++ Test-3 Pass +++ Normal mutex, Priority_inversion times = 3 for 3 runs +++ Test-4 Pass +++ Priority Inheritance mutex, Priority_inversion times = 0 for 3 runs +++ Test-5 Pass +++ Priority Protection mutex, Priority_inversion times = 0 for 3 runs +++ Test-6 Pass +++ ``` 在 ubuntu 20.04 glibc 版本是 2.31 ,而在 ubuntu 22.04 glibc 版本是 2.35 ,應該是某些<s>函數</s> 定義上不同或是兩個版本對於記憶體配置的方式不同,使得在 ubuntu 20.04 上即便有發生 Segmentation fault 但不至於終止。 :::danger 不要使用 `spoiler` 標示,充分揭露你的想法、嘗試、發現,和如何解決問題。 > 好 ::: > 嘗試用 `git reset` 指定到某些功能導向修改的 commit,執行對應的測試,觀察其行為並修正。 ## TODO: 在[實作輕量級的 Mutex Lock](/@sysprog/concurrency-mutex)的程式碼基礎,引入 [MutexShootout](https://github.com/markwaterman/MutexShootout) :::info MutexShootout 專案的目的是為了測試不同種的 mutex 效果,其中大多 mutex 是在 windows 上才有的 (作者也有提供 FreeBSD 的) >該實驗的目的是使用這些作者實作出來的 mutex 帶入 [perf-test](https://github.com/sysprog21/concurrent-programs/blob/master/mutex/perf-test/main.c) 的測試環境,用以比較 futex 、pthread、以及好幾種在 windows 環境下的 mutex ::: 在這個專案中,各個檔案的作用大致上如下: - MurmurHash3.cpp, MurmurHash3.h : 主要是提供對於 MurmurHash 的實作,用於到 'boost::uuid' 進行 hash 函數的計算 - hashing.hpp : 提供對 'boost::uuid' 計算 hash 值的函數 - lru_cache.hpp : 實作 thread-safe 的 LRU cache - alt_muteex.hpp : 在這實作出不同的 mutex - main.cpp : 生成測試數據,並比較不同的性能 - stopwatch.hpp : 計時用 嘗試合併時,碰到的第一個問題是命名和 boost 庫裡面的 load 衝突,所以將使用到 stdatomic.h 函數的都改成用 C++11 所定義的 atomic 觀察 boost 內對於 load 定義在 boost/serialization/nvp.hpp ``` void load( Archive & ar, nvp<T> & t , const unsigned int /* file_version */ ){ ar >> t.value(); } ``` 參考[官方文件](https://www.boost.org/doc/libs/1_74_0/libs/serialization/doc/archives.html) >其中 Archive 的定義 : An archive is defined by two complementary classes. One is for saving data while the other is for loading it. >而 nvp 參考 [官方文件](https://www.boost.org/doc/libs/1_51_0/boost/serialization/nvp.hpp) 指的是 "Name-Value Pair" 封裝了資料成對操作的功能 :::danger directory 是「目錄」,而非 folder,前者是 UNIX 用語。 data 是「資料」,而非「數據」 > 收到 ::: 我嘗試將除了 main.cpp 以外的檔案放入 [perf-test](https://github.com/sysprog21/concurrent-programs/tree/master/mutex/perf-test) 的目錄,然後參考 main.cpp 內的 [run_benchmark](https://github.com/markwaterman/MutexShootout/blob/master/main.cpp#L121) 改成 perf-test 的測試方法 > 目前只有測試過在 Linux 環境下執行,還需要嘗試看看windows環境的 > 因為作者在 [main.c](https://github.com/markwaterman/MutexShootout/blob/master/main.cpp#L41) 內有一段以及 readme ``` #if _WIN32 std::cerr << "Usage: " << argv[0] << " threadCount nolocks|std|boost|cs0|cs4k|srw\n"; ``` - std::mutex (VS 2017) : Windows only - boost::mutex : Implemented with a futex on Linux - srw_mutex : Windows only - cs_mutex_4K : Windows only - cs_mutex_nospin : Windows only - std::mutex(VS 2013) : Windows only - std::mutex (Linux) : Uses futex - std::mutex (FreeBSD) : only 所以可以觀察到我在 Ubuntu 環境下跑,std (futex) 和 boost (也是用futex) 的表現差不多,然後兩個都比 thread 表現還要好 > 備註:threadcount 為 4 [build/plot.py](https://github.com/LULser0204/concurrent-programs/blob/master/mutex/mutexshootout-test/build/plot.py) 可以設定數量 > 完整變更 : [commit feefe75](https://github.com/sysprog21/concurrent-programs/compare/master...LULser0204:concurrent-programs:master) ![linuxkernel](https://hackmd.io/_uploads/BJADilY8A.png) :::danger 注意用語: * directory 是「目錄」 * 超連結指向的頁面通常會有標題,你該避免說「這篇」或「這個」 ::: > 嘗試在 Windows 上執行 :::warning 無法在 windows 上使用 pthread.h 提供的 api ,有幾個方法解決 1.改用 windows.h : windows 此為 windows 提供的 api 2.改用 C++11 thread 提供的api 3.或者是另外安裝 pthread.h :具體方法可以參考 [在VS2015下建立執行thread的環境安裝教學](https://medium.com/arthur-chien/c-c-%E5%9C%A8vs2015%E4%B8%8B%E5%BB%BA%E7%AB%8B%E5%9F%B7%E8%A1%8Cthread%E7%9A%84%E7%92%B0%E5%A2%83-a519d13a27bf) ,只是 dll 要放 x64 <s>資料夾</s>的 ::: :::danger 如果想使用 boost library ,然後使用的是 Visual studio 2022 會發現一直無法成功 build,我卡在這邊卡超久,後來終於在官方的 [No support for msvc-toolset 14.4x (VS 2022, 17.10.x)](https://github.com/boostorg/boost/issues/914) 找到有人和我遇到一樣的問題 > 因為 b2 的建置腳本在 Visual Studio 的 " 版本判斷 " 腳本在 ( `tools/build/src/tools/msvc.jam` )裡面,是把 14.3 當成 Visual Studio 2022。但是 VS2022 最新版已把版本推到 14.40 了,結果就沒辦法正確判斷版本 > 英雄所見略同,恭喜你提升自己的視野 ::: >然後,這是在 windows 上的執行結果,分別是 "std:mutex (VS 2022)"、"srw_mutex"、"cs_mutex_4K"、"cs_mutex_nospin"、"boost::mutex" ![windowsmutex](https://hackmd.io/_uploads/SyqNCYq8C.png) > 這是將 windows 上和 linux 上的 mutex 進行比較 ![windowsplueslinux](https://hackmd.io/_uploads/SyDHiqcL0.png) 可以觀察到 Linux 下的 mutex 表現都比 windows 的好 ## TODO: 將[實作輕量級的 Mutex Lock](/@sysprog/concurrency-mutex)的成果整合到[建立 PThread 相容實作](/@sysprog/concurrency-thread-package)