一、多线程
多线程使用的是pthread库,写程序的时候需要引入头文件pthread.h, g++编译的时候需要加上该库的依赖“-lpthread”。
1 先看程序便于理解,代码下面有对注释的解释。下面的代码含义是创建两个线程,一个线程去计算某个变量的阶乘,另一个去计算从0到某个变量的和

#include <iostream>
#include <pthread.h>
#include <string.h>
void *thread1_fact(void *arg);  // 注释1
void *thread2_sum(void *arg);
int main() {
    pthread_t t_fact;  // 注释2
    pthread_t t_sum;
    int i = 10;
    if (pthread_create(&t_fact, NULL, thread1_fact, &i) != 0) {  // 注释3
        std::cout << "pthread_create() error";
        return -1;
    }
    if (pthread_create(&t_sum, NULL, thread2_sum, &i) != 0) {
        std::cout << "pthread_create() error";
        return -1;
    }
    pthread_join(t_fact, NULL);  // 注释4
    pthread_join(t_sum, NULL);
    return 0;
}
void *thread1_fact(void *arg) {
    int i = *(int*)arg; //注释5
    int fact = 1;
    while(i){
        fact *= i;
        i--;
    }
    std::cout << "thread1 get fact:" << fact << std::endl;
}

void *thread2_sum(void *arg) {
    int i = *(int*)arg; 
    int sum = 0;
    while (i>0) {
        sum += i;
        i--;
    }
    std::cout << "thread2 get sum:" << sum << std::endl;
}

输出:
thread1 get fact:3628800
thread2 get sum:55

2 对上面的函数的解析
注释1
首先声明函数,该函数是创建的线程要执行的函数,注意里面的参数,是无类型的指针
注释2
线程要根据线程ID区分,改变量用于保存线程的ID
注释3:
pthread_create()原型:
extern int pthread_create (pthread_t *__restrict __newthread,
const pthread_attr_t *__restrict __attr,
void (*__start_routine) (void ),
void *__restrict __arg) __THROWNL __nonnull ((1, 3));

包含四个参数如下
__newthread: 如果创建成功,改变量保存创建成功的线程ID
__attr: 传递线程属性参数,传递NULL时创建默认属性的线程
__start_routine: 相当于线程的main函数,创建好的线程执行该函数
__arg: 要传递给线程执行函数的参数,它其实是一个变量的地址,不传递参数时可以设置为NULL
该函数如果执行成功,则返回0,执行失败返回其他值
注释4
大家可以先把这行代码去掉看看效果,会发现可能没有任何输出,这并不是错误。这是由于main函数执行完毕即可结束,没有等待我们创建的线程结束。所以pthread_join(t_fact, NULL);的含义就是等待t_fact这个线程结束后,main函数才会结束。
注释5
如上面所说,传递过来的参数是一个无类型的指针,我们需要将其转换为我们需要的数据。

二、互斥锁
涉及到多线程必然会有互斥问题,上面的代码没有访问冲突,但是加入有两个线程一个将其增1,一个将其减1,这样如果没有互斥访问就可能存在错误。同上,先上代码便于理解,注释会在下文给出。
1 下面的代码含义是两个进程对某个bool变量互斥访问,此处不再解释多线程的问题,只解释互斥锁的写法

#include <iostream>
#include <netinet/in.h>
#include <pthread.h>

void *thread_write(void *arg);

pthread_mutex_t mutex;  // 注释1

int main() {
    pthread_mutex_init(&mutex, NULL);  //注释2
    pthread_t t_1;
    pthread_t t_2;
    if (pthread_create(&t_1, NULL, thread_write, NULL) != 0) {
        std::cout << "pthread_create() error";
        return -1;
    }
    if (pthread_create(&t_2, NULL, thread_write, NULL) != 0) {
        std::cout << "pthread_create() error";
        return -1;
    }
    pthread_join(t_1, NULL);
    pthread_join(t_2, NULL);
    pthread_mutex_destroy(&mutex); //注释3
    return 0;
}

void *thread_write(void *arg) {
    pthread_mutex_lock(&mutex);  //注释4
    std::cout << "one apply for the mutex successfully" << std::endl;
    pthread_mutex_unlock(&mutex);  //注释5
}

2 对上面注释的解释
注释1
定义一个互斥变量
注释2
将互斥变量初始化
注释3
结束后将互斥量销毁
注释4
申请该互斥锁,申请到的话可以执行下面的代码,申请失败则会阻塞,只能有一个线程可以申请到。
注释5
线程结束访问后释放互斥锁,可以让其他线程申请该锁。

补充:上面两个只是简单的介绍,还有其他原理和其他用法由于本人水平所限没有介绍,后期再慢慢更新,如有错误或者建议可以留言。

Logo

更多推荐