您的位置:

Linux下创建线程

一、线程的概念

线程是指进程内部的一个执行单元,也称为轻量级进程,它和进程一样可以独立执行、拥有独立的栈空间、程序计数器和寄存器等,但是多个线程可以共享进程的资源,如内存空间、文件、I/O。线程的创建和销毁都比进程更加的轻便快捷,因此多线程成为了提高系统性能和程序效率的一种重要方式。

二、线程的创建

Linux提供了几种方式创建线程:pthread_create()、clone()等。其中pthread_create()是比较常用的一个函数,其函数原型如下:

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

它的参数依次为:

1、指向线程标识符的指针;

2、线程属性,NULL表示使用默认属性;

3、指向函数的指针,该函数是新线程的入口地址;

4、函数的参数。

下面是一个简单的例子:

#include 
#include 
   
#include 
    

void *print_message_function(void *ptr);

int main()
{
    pthread_t thread1, thread2;
    char *message1 = "Thread 1";
    char *message2 = "Thread 2";
    int ret1, ret2;

    // 创建线程1
    ret1 = pthread_create(&thread1, NULL, print_message_function, (void *) message1);
    if (ret1 != 0)
    {
        printf("Create thread 1 failed!\n");
        exit(1);
    }

    // 创建线程2
    ret2 = pthread_create(&thread2, NULL, print_message_function, (void *) message2);
    if (ret2 != 0)
    {
        printf("Create thread 2 failed!\n");
        exit(1);
    }

    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);

    printf("Main function exits!\n");
    return 0;
}

void *print_message_function(void *ptr)
{
    char *message = (char *) ptr;
    printf("%s\n", message);
}

    
   
  

在上面的例子中,我们使用pthread_create()函数创建了2个线程,并传入一个字符串作为线程函数的参数。然后使用pthread_join()函数等待线程结束。

三、线程的同步

线程之间的同步通常需要互斥量、条件变量等机制。比如常用的互斥量pthread_mutex_t可以用来保护共享资源,pthread_cond_t则可以用来进行线程的条件等待与唤醒。

下面是一个使用互斥量保护共享资源的例子:

#include 
#include 
   
#include 
    

#define THREAD_NUM 5

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int sum = 0;

void *thread_function(void *arg);

int main()
{
    pthread_t threads[THREAD_NUM];

    // 创建多个线程
    for (int i = 0; i < THREAD_NUM; i++)
    {
        pthread_create(&threads[i], NULL, thread_function, NULL);
    }

    // 等待所有线程结束
    for (int i = 0; i < THREAD_NUM; i++)
    {
        pthread_join(threads[i], NULL);
    }

    printf("Sum = %d\n", sum);
    return 0;
}

void *thread_function(void *arg)
{
    int i;
    for (i = 0; i < 1000; i++)
    {
        pthread_mutex_lock(&mutex);
        sum++;
        pthread_mutex_unlock(&mutex);
    }

    pthread_exit(NULL);
}

    
   
  

在这个例子中,我们使用pthread_mutex_t来保护sum这个共享资源,多个线程会去累加这个值。由于多个线程同时访问sum,如果没有互斥保护,会产生竞争状态,导致结果不正确。因此我们使用互斥量对共享资源进行保护,保证线程之间的同步。

四、线程的销毁

线程的销毁通常是在线程函数中通过pthread_exit()函数进行,也可以使用pthread_cancel()函数强制取消线程。同时可以使用pthread_join()函数等待线程结束,防止进程过早退出,导致线程没有执行完毕。

下面是一个使用pthread_cancel()函数强制取消线程的例子:

#include 
#include 
   
#include 
    

void *thread_function(void *arg);

int main()
{
    pthread_t thread_id;
    int ret;

    // 创建线程
    ret = pthread_create(&thread_id, NULL, thread_function, NULL);
    if (ret != 0)
    {
        printf("Create thread failed!\n");
        exit(1);
    }

    // 睡眠 5 秒
    sleep(5);

    // 强制杀死线程
    pthread_cancel(thread_id);

    printf("Main function exits!\n");
    return 0;
}

void *thread_function(void *arg)
{
    int i;

    // 设置取消状态
    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);

    // 设置取消类型
    pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);

    for (i = 0; ; i++)
    {
        printf("Thread running...\n");
        sleep(1);
    }

    pthread_exit(NULL);
}

    
   
  

在上面的例子中,我们使用了pthread_cancel()函数强制取消线程。同时在线程函数中设置了取消状态和取消类型。

五、线程的属性

线程的属性可以用来调整线程的优先级、栈大小等。pthread_attr_t是线程属性的类型,Linux提供了一些函数来进行线程属性的设置和获取,如pthread_attr_init()、pthread_attr_setstacksize()、pthread_attr_getschedpolicy()等。

下面是一个设置线程栈大小的例子:

#include 
#include 
   
#include 
    

void *thread_function(void *arg);

int main()
{
    pthread_t thread_id;
    pthread_attr_t attr;
    size_t stacksize;
    int ret;

    // 初始化线程属性
    pthread_attr_init(&attr);
    pthread_attr_getstacksize(&attr, &stacksize);
    printf("Default stack size = %d KB\n", (int) stacksize / 1024);

    // 设置线程栈大小
    pthread_attr_setstacksize(&attr, 1024 * 1024);
    pthread_attr_getstacksize(&attr, &stacksize);
    printf("New stack size = %d KB\n", (int) stacksize / 1024);

    // 创建线程
    ret = pthread_create(&thread_id, &attr, thread_function, NULL);
    if (ret != 0)
    {
        printf("Create thread failed!\n");
        exit(1);
    }

    // 等待线程结束
    pthread_join(thread_id, NULL);

    printf("Main function exits!\n");
    return 0;
}

void *thread_function(void *arg)
{
    int i;

    for (i = 0; i < 10; i++)
    {
        printf("Thread running...\n");
        sleep(1);
    }

    pthread_exit(NULL);
}

    
   
  

在上面的例子中,我们使用了pthread_attr_setstacksize()函数设置了线程的栈大小为1MB。

六、总结

本文介绍了Linux下创建线程的方法及相关知识。具体来说,我们讲解了线程的概念、创建、同步、销毁和属性等内容。通过本文的学习,读者可以掌握如何使用Linux提供的相关函数来创建线程,并进行进一步的开发。