如果要记录因为获取不到锁而切换线程可以用这个封装的锁替代
#pragma once
#include <mutex>
#include <atomic>
#include <iostream>
#include "logger.h"
class StatisticMutex {
std::mutex mtx;
std::atomic<size_t> contention_count{0}; // 统计竞争次数
public:
void enter() {
// 尝试非阻塞获取,若失败则记录竞争
if (!mtx.try_lock()) {
logInfo("NYX ++1 \n");
contention_count.fetch_add(1, std::memory_order_relaxed);
mtx.lock(); // 阻塞等待
}
}
bool try_lock() {
bool success = mtx.try_lock();
if (!success) {
contention_count.fetch_add(1, std::memory_order_relaxed);
}
return success;
}
void leave() {
mtx.unlock();
}
size_t get_contention_count() const {
return contention_count.load(std::memory_order_relaxed);
}
};
用这个脚本统计线程下线程切换的次数每秒
while true; do cat /proc/9759/status | grep ctxt_switches; sleep 1; done
/proc# while true; do cat /proc/9759/status | grep ctxt_switches; sleep 1; done
voluntary_ctxt_switches: 6384
nonvoluntary_ctxt_switches: 408
voluntary_ctxt_switches: 6393
nonvoluntary_ctxt_switches: 409
voluntary_ctxt_switches: 6403
nonvoluntary_ctxt_switches: 410
主动切换次数大约9次每秒 大概有什么sleep 或者频繁的唤醒并且wait...
strace -e trace=nanosleep,futex,read,write -p 9759
strace: Process 9759 attached
通过strace发现确实有8次sleep 才想起是自己加的调试代码为了信标帧可以更频繁的发送 让手机可以识别
futex(0x2e08ca50, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME, 0, NULL, FUTEX_BITSET_MATCH_ANY) = 0
write(1, "[2026-05-07 19:36:21.060491] [97"..., 85) = 85
futex(0x2e12f6b0, FUTEX_WAKE_PRIVATE, 1) = 1
write(61, "\252U\220\0\0\0\224\0\200\0\0\0\377\377\377\377\377\3778\257)3DU8\257)3DU \375"..., 151) = 151
nanosleep({tv_sec=0, tv_nsec=100000000}, 0x7ef8bfcfd0) = 0
write(61, "\252U\220\0\0\0\224\0\200\0\0\0\377\377\377\377\377\3778\257)3DU8\257)3DU \375"..., 151) = 151
nanosleep({tv_sec=0, tv_nsec=100000000}, 0x7ef8bfcfd0) = 0
write(61, "\252U\220\0\0\0\224\0\200\0\0\0\377\377\377\377\377\3778\257)3DU8\257)3DU \375"..., 151) = 151
nanosleep({tv_sec=0, tv_nsec=100000000}, 0x7ef8bfcfd0) = 0
write(61, "\252U\220\0\0\0\224\0\200\0\0\0\377\377\377\377\377\3778\257)3DU8\257)3DU \375"..., 151) = 151
nanosleep({tv_sec=0, tv_nsec=100000000}, 0x7ef8bfcfd0) = 0
write(61, "\252U\220\0\0\0\224\0\200\0\0\0\377\377\377\377\377\3778\257)3DU8\257)3DU \375"..., 151) = 151
nanosleep({tv_sec=0, tv_nsec=100000000}, 0x7ef8bfcfd0) = 0
write(61, "\252U\220\0\0\0\224\0\200\0\0\0\377\377\377\377\377\3778\257)3DU8\257)3DU \375"..., 151) = 151
nanosleep({tv_sec=0, tv_nsec=100000000}, 0x7ef8bfcfd0) = 0
write(61, "\252U\220\0\0\0\224\0\200\0\0\0\377\377\377\377\377\3778\257)3DU8\257)3DU \375"..., 151) = 151
nanosleep({tv_sec=0, tv_nsec=100000000}, 0x7ef8bfcfd0) = 0
write(61, "\252U\220\0\0\0\224\0\200\0\0\0\377\377\377\377\377\3778\257)3DU8\257)3DU \375"..., 151) = 151
nanosleep({tv_sec=0, tv_nsec=100000000}, 0x7ef8bfcfd0) = 0
futex(0x2e08ca50, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME, 0, NULL, FUTEX_BITSET_MATCH_ANY) = 0
改完之后就是标准的1s一次
while true; do cat /proc/21961/status | grep ctxt_switches; sleep 1; done
voluntary_ctxt_switches: 91
nonvoluntary_ctxt_switches: 3
voluntary_ctxt_switches: 92
nonvoluntary_ctxt_switches: 3
voluntary_ctxt_switches: 93
nonvoluntary_ctxt_switches: 3