C/C++基于线程的并发编程(一):初识线程编程

什么是线程

线程就是运行在进程上下文中的单元。进程是由多个线程组成,最简单的进程由一个线程组成,而这个线程就叫做主线程。线程由内核自动调度。每个线程都有自己的线程上下文,包括一个唯一的线程ID、栈、栈指针、程序计数器、通用目的寄存器和条件码。 由于多线程编程均在同一进程中,所以线程之间共享这个进程虚拟地址空间的所有内容,包括它的代码、数据、堆、共享库和打开文件等。这也是的线程的并发编程的引发安全性问题的原因,后续会对线程安全进行展开阐述。 如上图所示,进程开始生命周期时都是单一线程,而这个线程称为主线程。在某一个时刻,主线程创建一个对等线程,从这个时刻开始,两个线程就并发的运行。主线程执行延迟调用时,如read或者sleep操作,或者因为被内核的定时器中断,就会通过上下文切换传递到对等线程。而对等线程执行一段时间,再传递回主线程,依次类推。 线程的执行不同于进程,因为线程的上下文比进程的上下文小得多,所以线程上下文的效率要比进程的上下文切换快得多。另外,线程不像进程那样,不是按照严格的父子层次来组织的。主线程和其他线程的区别仅在于它总是进程第一个运行的线程。

多线程编程

介绍完线程的一些基础知识,下面用C和C++分别实现多线程编程。

C++的多线程编程

#include <iostream>
#include <thread>

using namespace std;
void func()
{
          
   
    for(int i = 0; i < 5; ++i)
    {
          
   
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
        cout << "thread id:" << this_thread::get_id() << " run func" << endl;
    }
}

int main()
{
          
   
    cout << "mainthread id: " << this_thread::get_id() << endl;
    std::thread t1 = std::thread(func);		// 申请线程并在线程中运行func函数
    std::thread t2 = std::thread(func);		// 申请线程并在线程中运行func函数

    t1.join();		// 等待t1线程结束
    t2.join();		// 等待t2线程结束

    return 0;
}

以下程序的输出如下:

mainthread id: 1
thread id:2 run func
thread id:3 run func
thread id:2 run func
thread id:3 run func
thread id:2 run func
thread id:3 run func
thread id:2 run func
thread id:3 run func
thread id:2 run func
thread id:3 run func

主线程的线程id为1,当线程对象申请开始,线程就已经开始执行func函数。id为2的线程和id为3的线程每隔500ms进行输出。而join函数的调用,会让主线程等待子线程运行结束后在进行退出。

C的多线程编程

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

void* func(void *val)
{
          
   
    for(int i = 0; i < 5; ++i)
    {
          
   
        usleep(500 * 1000);
        printf("thread id: 0x%x, run func
", (unsigned int)pthread_self());
    }

    return NULL;
}

int main()
{
          
   
    printf("mainthread id: 0x%x
", (unsigned int)pthread_self());
    pthread_t t1;
    pthread_t t2;

    pthread_create(&t1, NULL, func, NULL);	// 创建线程
    pthread_create(&t2, NULL, func, NULL);	// 创建线程

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

    return 0;
}

以下程序的输出如下:

mainthread id: 0xf7da0740
thread id: 0xf7d9f700, run func
thread id: 0xf759e700, run func
thread id: 0xf7d9f700, run func
thread id: 0xf759e700, run func
thread id: 0xf7d9f700, run func
thread id: 0xf759e700, run func
thread id: 0xf759e700, run func
thread id: 0xf7d9f700, run func
thread id: 0xf7d9f700, run func
thread id: 0xf759e700, run func

输出效果和C++实现类似,两个线程交替调用func函数。该环境跑在linux。

经验分享 程序员 微信小程序 职场和发展