ZBLOG

linux 下如何保证一个线程函数同同时只能运行一个

在 Linux 下,可以通过多种方式保证一个线程函数在同一时间只能运行一个实例(即线程安全)。以下是几种常见的方法:


1. 使用互斥锁(Mutex)

最常用的方法,确保同一时间只有一个线程能进入临界区。

示例代码(C++11 <mutex>

  1. #include <iostream>
  2. #include <thread>
  3. #include <mutex>
  4. std::mutex mtx; // 全局互斥锁
  5. void thread_func() {
  6. std::lock_guard<std::mutex> lock(mtx); // 自动加锁,离开作用域解锁
  7. std::cout << "Thread ID: " << std::this_thread::get_id() << " is running." << std::endl;
  8. // ... 临界区代码 ...
  9. }
  10. int main() {
  11. std::thread t1(thread_func);
  12. std::thread t2(thread_func);
  13. t1.join();
  14. t2.join();
  15. return 0;
  16. }
  • std::lock_guard:RAII机制,防止忘记解锁。
  • std::unique_lock:更灵活,可以手动控制加解锁。

2. 使用原子变量(Atomic Flag)

适用于简单场景,避免锁的开销。

示例代码

  1. #include <atomic>
  2. #include <thread>
  3. std::atomic_flag flag = ATOMIC_FLAG_INIT;
  4. void thread_func() {
  5. if (flag.test_and_set()) { // 检查是否已被占用
  6. return; // 如果已经在运行则退出
  7. }
  8. // ... 临界区代码 ...
  9. flag.clear(); // 释放标志位
  10. }
  • 适用场景:轻量级同步需求。

3. POSIX 信号量(Semaphore)

适用于跨进程或更复杂的同步控制。

示例代码

  1. #include <semaphore.h>
  2. #include <pthread.h>
  3. sem_t sem;
  4. void* thread_func(void*) {
  5. sem_wait(&sem); // P操作(获取信号量)
  6. // ... 临界区代码 ...
  7. sem_post(&sem); // V操作(释放信号量)
  8. }
  9. int main() {
  10. sem_init(&sem, 0, 1); // 初始值为1(二进制信号量)
  11. pthread_t t1, t2;
  12. pthread_create(&t1, NULL, thread_func, NULL);
  13. pthread_create(&t2, NULL, thread_func, NULL);
  14. pthread_join(t1, NULL);
  15. pthread_join(t2, NULL);
  16. sem_destroy(&sem);
  17. }

4. C++11 call_once

确保某个函数在多线程环境下只执行一次。

示例代码

  1. #include <mutex>
  2. #include <thread>
  3. std::once_flag flag;
  4. void init_function() {
  5. std::cout << "This runs only once!" << std::endl;
  6. }
  7. void thread_func() {
  8. std::call_once(flag, init_function);
  9. }
  • 适用场景:单例初始化等。

5. Linux Futex(快速用户态互斥锁)

高性能场景下的底层同步机制,如 Nginx、Redis。

示例伪代码

  1. // (需结合汇编或系统调用实现)

总结

方法 适用场景 特点
Mutex 通用多线程同步 C++标准库支持
Atomic Flag 轻量级标志位检查 无锁但功能有限
Semaphore 跨进程/复杂同步 POSIX标准
call_once 单次初始化 C++11特性
Futex 高性能底层开发 Linux特有

选择合适的方式取决于具体需求:

  • 推荐默认用 std::mutex(简单可靠)。
  • 低延迟场景考虑原子变量或无锁结构
  • 跨进程用信号量或共享内存+互斥锁

如果需要进一步优化性能,可研究自旋锁(pthread_spinlock_t)或读写锁(std::shared_mutex)。


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://golang.0voice.com/?id=23140

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?