ZBLOG

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

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


1. 使用互斥锁(Mutex)

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

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

#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx; // 全局互斥锁

void thread_func() {
    std::lock_guard<std::mutex> lock(mtx); // 自动加锁,离开作用域解锁
    std::cout << "Thread ID: " << std::this_thread::get_id() << " is running." << std::endl;
    // ... 临界区代码 ...
}

int main() {
    std::thread t1(thread_func);
    std::thread t2(thread_func);

    t1.join();
    t2.join();

    return 0;
}
  • std::lock_guard:RAII机制,防止忘记解锁。
  • std::unique_lock:更灵活,可以手动控制加解锁。

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

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

示例代码

#include <atomic>
#include <thread>

std::atomic_flag flag = ATOMIC_FLAG_INIT;

void thread_func() {
    if (flag.test_and_set()) { // 检查是否已被占用
        return; // 如果已经在运行则退出
    }
    
    // ... 临界区代码 ...
    
    flag.clear(); // 释放标志位
}
  • 适用场景:轻量级同步需求。

3. POSIX 信号量(Semaphore)

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

示例代码

#include <semaphore.h>
#include <pthread.h>

sem_t sem;

void* thread_func(void*) {
    sem_wait(&sem); // P操作(获取信号量)
    
    // ... 临界区代码 ...
    
    sem_post(&sem); // V操作(释放信号量)
}

int main() {
    sem_init(&sem, 0, 1); // 初始值为1(二进制信号量)

    pthread_t t1, t2;
    pthread_create(&t1, NULL, thread_func, NULL);
    pthread_create(&t2, NULL, thread_func, NULL);

    pthread_join(t1, NULL);
    pthread_join(t2, NULL);

    sem_destroy(&sem);
}

4. C++11 call_once

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

示例代码

#include <mutex>
#include <thread>

std::once_flag flag;

void init_function() {
     std::cout << "This runs only once!" << std::endl;
}

void thread_func() {
     std::call_once(flag, init_function);
}
  • 适用场景:单例初始化等。

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

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

示例伪代码

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

总结

方法 适用场景 特点
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

注册

已经有帐号?