【Linux】【应用层】多线程编程

一、线程创建

Linux 中的 pthread_create() 函数用来创建线程,它声明在头文件中,语法格式如下:

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

各个参数的含义是:

  1. pthread_t *thread:传递一个 pthread_t 类型的指针变量,也可以直接传递某个 pthread_t 类型变量的地址。pthread_t 是一种用于表示线程的数据类型,每一个 pthread_t 类型的变量都可以表示一个线程。
  2. const pthread_attr_t *attr:用于手动设置新建线程的属性,例如线程的调用策略、线程所能使用的栈内存的大小等。大部分场景中,我们都不需要手动修改线程的属性,将 attr 参数赋值为 NULL,pthread_create() 函数会采用系统默认的属性值创建线程。
  3. void *(*start_routine) (void *):以函数指针的方式指明新建线程需要执行的函数,该函数的参数最多有 1 个(可以省略不写),形参和返回值的类型都必须为 void* 类型。void* 类型又称空指针类型,表明指针所指数据的类型是未知的。使用此类型指针时,我们通常需要先对其进行强制类型转换,然后才能正常访问指针指向的数据。

如果该函数有返回值,则线程执行完函数后,函数的返回值可以由 pthread_join() 函数接收。有关 phtread_join()

  1. void *arg:指定传递给 start_routine 函数的实参,当不需要传递任何数据时,将 arg 赋值为 NULL 即可。
    如果成功创建线程,pthread_create() 函数返回数字 0,反之返回非零值。各个非零值都对应着不同的宏,指明创建失败的原因,常见的宏有以下几种:
    EAGAIN:系统资源不足,无法提供创建线程所需的资源。
    EINVAL:传递给 pthread_create() 函数的 attr 参数无效。
    EPERM:传递给 pthread_create() 函数的 attr 参数中,某些属性的设置为非法操作,程序没有相关的设置权限。

以上这些宏都声明在 头文件中,如果程序中想使用这些宏,需提前引入此头文件。

二、线程通信

在Linux中,多线程通信可以使用许多不同的机制。以下是一些常用的多线程通信方法:

  1. 互斥锁(mutex):互斥锁用于保护共享资源,以便在任何时候只有一个线程可以访问它。当一个线程获得互斥锁后,其他线程将被阻塞,直到该线程释放锁。
  2. 条件变量(condition variable):条件变量用于在线程之间传递信息,因为它们允许一个线程等待另一个线程满足某个条件。当条件变量满足时,线程可以继续执行;否则,线程将被阻塞。
  3. 信号量(semaphore):信号量用于控制对共享资源的访问,但它们可以同时允许多个线程访问资源。信号量具有计数器,当计数器为0时,调用sem_wait()函数的线程将被阻塞,直到另一个线程调用sem_post()函数增加计数器。
  4. 管道(pipe):管道可以用于在进程之间传递数据,也可以用于在线程之间传递数据。在多线程环境中,可以使用匿名管道或命名管道来实现线程之间的通信。
  5. 共享内存(shared memory):共享内存允许多个线程访问同一块内存区域。这种方式是最快的 IPC 方式,但需要开发者自行处理同步问题。

这些机制可以单独或组合使用。例如,互斥锁和条件变量经常一起使用,以便在线程之间保护共享资源并传递信息。在实践中,选择哪种方法通常取决于应用程序的需求,以及性能、可维护性等方面的考虑。

三、示例代码

#include 
#include 

static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t  cond = PTHREAD_COND_INITIALIZER;

static int data_ready = 0;
static int data = 0;

void* thread_func(void *arg)
{
    while (1) {
        pthread_mutex_lock(&lock);
        while (!data_ready) {
            pthread_cond_wait(&cond, &lock);
        }
        std::cout << "Data received: " << data << std::endl;
        data_ready = 0;
        pthread_mutex_unlock(&lock);
    }
}

int main(int argc, char **argv)
{
    pthread_t tid;
    pthread_create(&tid, NULL, thread_func, NULL);

    int input;
    while (1) {
        std::cin >> input;

        pthread_mutex_lock(&lock);
        data = input;
        data_ready = 1;
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&lock);
    }

    return 0;
}

pthread不是linux下的默认的库,也就是在链接的时候,无法找到phread库中join函数的入口地址,链接会失败。因此需要编译命令时,附加
-lpthread 参数。(-l是L是小写 不是i的大写I) g++ main.cpp -o main -lpthread

你可能感兴趣的:(c++,开发语言)