Linux系统怎么创建线程

发布时间:2022-01-26 10:58:38 作者:柒染
来源:亿速云 阅读:168
# Linux系统怎么创建线程

## 1. 线程的基本概念

### 1.1 什么是线程

线程(Thread)是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。一个进程可以包含多个线程,这些线程共享进程的资源(如内存空间、文件描述符等),但每个线程拥有独立的程序计数器、寄存器集合和栈空间。

与进程相比,线程的创建和切换开销更小,通信更方便(因为共享内存空间),因此在现代操作系统中被广泛使用。

### 1.2 线程与进程的区别

| 特性         | 进程                     | 线程                     |
|--------------|--------------------------|--------------------------|
| 资源分配     | 独立的内存空间           | 共享进程的内存空间       |
| 创建开销     | 较大                     | 较小                     |
| 通信方式     | 管道、消息队列、共享内存等 | 直接读写共享变量         |
| 上下文切换   | 开销大                   | 开销小                   |
| 独立性       | 一个进程崩溃不影响其他进程 | 一个线程崩溃可能导致整个进程终止 |

## 2. Linux线程实现方式

### 2.1 LinuxThreads

早期的Linux线程实现,现在已经基本被NPTL取代。主要特点:
- 每个线程对应一个独立的进程ID
- 信号处理存在问题
- 性能较差

### 2.2 NPTL (Native POSIX Threads Library)

现代Linux系统默认使用的线程实现(自Linux 2.6起):
- 真正的1:1线程模型(每个用户线程对应一个内核线程)
- 高性能设计
- 更好的信号处理
- 完全兼容POSIX标准

可以通过命令查看系统使用的线程实现:
```bash
getconf GNU_LIBPTHREAD_VERSION

3. POSIX线程库(pthread)

3.1 pthread简介

POSIX线程(pthread)是IEEE制定的线程标准接口,Linux通过NPTL实现了这一标准。使用pthread需要包含头文件<pthread.h>,并在编译时链接-lpthread库。

3.2 基本线程操作

3.2.1 创建线程

#include <pthread.h>

int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                  void *(*start_routine) (void *), void *arg);

参数说明: - thread: 用于存储新线程ID的指针 - attr: 线程属性,NULL表示默认属性 - start_routine: 线程执行的函数 - arg: 传递给线程函数的参数

返回值:成功返回0,失败返回错误码

3.2.2 线程终止

线程可以通过以下方式终止: 1. 从线程函数中return 2. 调用pthread_exit() 3. 被其他线程取消(pthread_cancel()

void pthread_exit(void *retval);

3.2.3 等待线程结束

int pthread_join(pthread_t thread, void **retval);

3.2.4 线程分离

int pthread_detach(pthread_t thread);

3.3 线程同步机制

3.3.1 互斥锁(Mutex)

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_destroy(pthread_mutex_t *mutex);

3.3.2 条件变量(Condition Variable)

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_destroy(pthread_cond_t *cond);

3.3.3 读写锁(Read-Write Lock)

pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;

int pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr);
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

4. 线程属性

4.1 常用线程属性

pthread_attr_t attr;
pthread_attr_init(&attr);

// 设置分离状态
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

// 设置栈大小
size_t stacksize = 1024*1024;  // 1MB
pthread_attr_setstacksize(&attr, stacksize);

// 设置调度策略
pthread_attr_setschedpolicy(&attr, SCHED_FIFO);

// 使用属性创建线程
pthread_create(&thread, &attr, start_routine, arg);

// 销毁属性对象
pthread_attr_destroy(&attr);

4.2 线程优先级

struct sched_param param;
param.sched_priority = 50;
pthread_attr_setschedparam(&attr, &param);
pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);

5. 线程安全与可重入函数

5.1 线程安全函数

线程安全函数是指在多线程环境下能够正确执行的函数,通常通过以下方式实现: - 不使用全局或静态变量 - 使用互斥锁保护共享数据 - 使用线程局部存储

5.2 可重入函数

可重入函数是线程安全函数的子集,特点: - 不依赖全局或静态变量 - 不调用不可重入函数 - 不使用静态数据结构

6. 线程局部存储

6.1 POSIX线程特定数据

pthread_key_t key;

void destructor(void *value) {
    free(value);
}

pthread_key_create(&key, destructor);

void *value = malloc(100);
pthread_setspecific(key, value);

void *data = pthread_getspecific(key);

6.2 GCC的__thread关键字

static __thread int tls_var;

7. 线程取消

7.1 取消点

取消点是线程检查是否被取消的位置,包括: - 显式调用pthread_testcancel() - 某些阻塞系统调用(如read、write、sleep等)

7.2 取消类型

int oldtype;
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);

8. 线程与信号

8.1 信号处理

pthread_sigmask(SIG_BLOCK, &set, NULL);

8.2 等待信号

int sig;
sigwait(&set, &sig);

9. 线程池实现

9.1 基本结构

typedef struct {
    pthread_t *threads;
    int thread_count;
    task_queue_t queue;
    pthread_mutex_t lock;
    pthread_cond_t cond;
    int shutdown;
} thread_pool_t;

9.2 工作线程函数

void *worker_thread(void *arg) {
    thread_pool_t *pool = (thread_pool_t *)arg;
    
    while (1) {
        pthread_mutex_lock(&pool->lock);
        
        while (queue_empty(&pool->queue) && !pool->shutdown) {
            pthread_cond_wait(&pool->cond, &pool->lock);
        }
        
        if (pool->shutdown) {
            pthread_mutex_unlock(&pool->lock);
            pthread_exit(NULL);
        }
        
        task_t task = queue_pop(&pool->queue);
        pthread_mutex_unlock(&pool->lock);
        
        task.function(task.arg);
    }
    
    return NULL;
}

10. 性能考虑与最佳实践

10.1 线程数量

10.2 避免竞争

10.3 调试技巧

11. 示例代码

11.1 简单线程创建

#include <stdio.h>
#include <pthread.h>

void *print_hello(void *arg) {
    printf("Hello from thread!\n");
    return NULL;
}

int main() {
    pthread_t thread;
    pthread_create(&thread, NULL, print_hello, NULL);
    pthread_join(thread, NULL);
    return 0;
}

11.2 生产者消费者模型

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

#define BUFFER_SIZE 10

int buffer[BUFFER_SIZE];
int count = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

void *producer(void *arg) {
    for (int i = 0; i < 20; i++) {
        pthread_mutex_lock(&mutex);
        
        while (count == BUFFER_SIZE) {
            pthread_cond_wait(&cond, &mutex);
        }
        
        buffer[count++] = i;
        printf("Produced: %d\n", i);
        
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&mutex);
        
        usleep(100000);
    }
    return NULL;
}

void *consumer(void *arg) {
    for (int i = 0; i < 20; i++) {
        pthread_mutex_lock(&mutex);
        
        while (count == 0) {
            pthread_cond_wait(&cond, &mutex);
        }
        
        int item = buffer[--count];
        printf("Consumed: %d\n", item);
        
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&mutex);
        
        usleep(200000);
    }
    return NULL;
}

int main() {
    pthread_t prod, cons;
    pthread_create(&prod, NULL, producer, NULL);
    pthread_create(&cons, NULL, consumer, NULL);
    
    pthread_join(prod, NULL);
    pthread_join(cons, NULL);
    
    return 0;
}

12. 常见问题与解决方案

12.1 线程创建失败

可能原因: - 资源限制(ulimit -u查看用户线程限制) - 内存不足 - 达到系统线程数上限

解决方案: - 检查errno值 - 调整系统限制(/etc/security/limits.conf

12.2 死锁

预防措施: - 按固定顺序获取多个锁 - 使用pthread_mutex_trylock() - 设置锁超时

12.3 性能瓶颈

优化方向: - 减少锁竞争 - 使用线程局部存储 - 考虑无锁算法

13. 现代C++中的线程

13.1 std::thread

#include <iostream>
#include <thread>

void thread_function() {
    std::cout << "Hello from thread!\n";
}

int main() {
    std::thread t(thread_function);
    t.join();
    return 0;
}

13.2 高级特性

14. 总结

Linux系统通过POSIX线程库(pthread)提供了强大的多线程编程支持。创建线程的基本步骤包括: 1. 定义线程函数 2. 创建线程属性(可选) 3. 调用pthread_create() 4. 管理线程生命周期(join/detach) 5. 使用同步机制保护共享数据

在多线程编程中,正确性比性能更重要。务必注意线程安全、避免竞争条件和死锁。现代C++也提供了更高级的线程抽象,可以根据项目需求选择合适的工具。

通过合理使用多线程,可以显著提高程序性能,特别是在多核CPU上。但同时也要注意线程带来的复杂性,在简单场景下,单线程配合事件驱动模型可能是更好的选择。 “`

推荐阅读:
  1. 线程 队列 创建线程
  2. 线程 NSThread 创建线程

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

linux

上一篇:Linux系统pam的服务模块及如何认证

下一篇:@Transactional注解怎么用

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》