Linux系统编程——线程

目录

一、进程与线程

二、线程开发

三、线程同步

互斥锁:

条件变量:


线程中不能使用return

一、进程与线程

  1. 线程的概念:
    • 线程是进程中的一条执行流,是CPU调度的最小单元,一个进程里最少有一个线程
  2. 线程与进程的区别
    • 进程为资源分配的最小单元,线程为执行的最小单位
    • 进程具有自己独立的内存空间,当一个进程崩溃时,由于是独立的内存空间,所以不会影响其他进程的运行。线程是在进程内运行的,一个进程可以拥有多个线程,且进程是资源分配的最小单元,所以当进程崩溃或者线程崩溃,那么其他共用一个进程的线程就会崩溃。
    • 进程之间的切换开销较大,线程之间的切换开销较小
    • 同一个进程内可以拥有多个线程,一个线程只能存在于一个进程之中
    • 进程通信通过:管道、消息队列、信号、共享内存等等。线程之间的通信通过全局数据、函数传参。
  3. 线程优点:
    • 占用资源少,创建进程比创建线程的代价大
    • 线程切换开销小
    • 线程之间的通信更加灵活
  4. 线程缺点:
    • 在变成难度上较高
    • 可能会有较大的性能损耗,这里的损耗指,如果计算密集型线程的数量比可用的处理器多,那么就会增加了额外的同步和调度开销,而可用的资源不变。
    • 缺乏访问控制
    • 线程之间缺乏保护

二、线程开发

  • 函数介绍:
函数名作用
pthread_create
创建线程,成功返回0
pthread_exit
线程退出,成功返回0
pthread_join
线程等待,调用该函数的将会一直阻塞,知道该进程标识符所对应的进程通过pthread_exit退出或者运行结束
pthread_detach

pthread_detach函数把指定的线程转变为脱离状态。

参数为所对应线程的ID

pthread_self

线程ID的获取,该函数为在线程内需要获取ID时的函数

该函数没有参数。

pthread_equal

对线程ID进行比较。该函数的参数分别为两个所比较线程的ID。

  • 函数参数介绍
    • pthread_create:
      • 第一个参数为线程ID
      • 第二个为定制不同的线程属性,暂时设为NULL
      • 第三个为:返回值为void*且参数为void*的函数指针
      • 第四个为第三个参数所对应函数的参数
    • pthread_exit:
      • 参数为传递给pthread_join的退出码,该参数为一级指针,该退出码需要使用static关键字或者全局变量。
    • pthread_join:
      • 第一个参数为等待退出的线程ID
      • 第二个参数为接收对应线程退出所发送的退出码,为二级指针,如果不在意退出码的话可以设置为NULL
  • 实战
    #include <stdio.h>
    #include <pthread.h>
    
    //int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
    
    void* thread1(void *arg)
    {
            static char *ret = "thread1 quit success!\n";
    
            printf("thread:%ld\n",(unsigned long)pthread_self());
            printf("param = %d\n",*((int *)arg));
    
            pthread_exit((void*)ret);
    }
    
    int main()
    {
            pthread_t t1;
            int param = 100;
            char *pret;
    
            if(pthread_create(&t1,NULL,thread1,(void *)&param) < 0){
                    printf("thread create error\n");
            }
    
            printf("main:%ld\n",(unsigned long)pthread_self());
    
            pthread_join(t1,(void **)&pret);
    
            printf("thread quit:%s\n",pret);
    
            return 0;
    }
    

三、线程同步

  1. 互斥锁:

  • 当我们有多个线程对一个变量进行操作时,如果恰巧有多个线程同时进行操作,那么该变量得数值就不会如我们想象的样子进行变化了。此时我们需要对操作该变量的线程进行限制,此时就用到了互斥锁来对变量进行同步,当我们对变量进行操作时,先进行上锁,后进行操作变量,当操作完后进行解锁。(对于在单个cpu上进行的多个线程来说,当我们线程解锁完后,需要进行短暂的延迟,来让其他线程对cpu进行竞争)
    1. 函数介绍
      函数名称函数作用
      pthread_mutex_init
      进行创建互斥锁
      pthread_mutex_destroy
      销毁互斥锁
      pthread_mutex_lock
      上锁
      pthread_mutex_unlock
      解锁
    2. 函数参数

      1. pthread_mutex_init

        1. 第一个参数为互斥变量,用pthread_mutex_t数据类型表示。在使用互斥变量前必须对它进行初始化,可以把它置为常量PTHREAD_MUTEX_INITIALIZER(只对静态分配的互斥量)

        2. 第二个参数为互斥锁的属性,暂时设做NULL

      2. pthread_mutex_destroy:参数为互斥变量

      3. pthread_mutex_lock和pthread_mutex_unlock:参数都为互斥变量

    3. 实战

      include <stdio.h>
      #include <pthread.h>
      #include <unistd.h>
      
      //int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
      
      int g_data = 0;
      pthread_mutex_t mutex;
      
      void* thread1(void *arg)
      {
              int i = 0;
      
              pthread_mutex_lock(&mutex);
              while(1){
                      printf("t1:%ld\n",(unsigned long)pthread_self());
                      sleep(1);
                      if(i > 5){
                              break;
                      }
                      i++;
              }
              printf("te quit======================\n");
      
              pthread_mutex_unlock(&mutex);
      }
      
      void* thread2()
      {
              while(1){
                      pthread_mutex_lock(&mutex);
                      printf("t2:%ld\n",(unsigned long)pthread_self());
                      pthread_mutex_unlock(&mutex);
      
                      sleep(1);
              }
      }
      
      int main()
      {
              pthread_t t1;
              pthread_t t2;
              int param = 100;
              printf("main:%ld\n",(unsigned long)pthread_self());
      
              pthread_mutex_init(&mutex,NULL);
      
              if(pthread_create(&t1,NULL,thread1,(void *)&param) < 0){
                      printf("thread1 create error\n");
              }
              if(pthread_create(&t2,NULL,thread2,NULL) < 0){
                      printf("thread2 create error");
              }
      
              printf("main: %d\n",g_data++);
      
              pthread_join(t1,NULL);
              pthread_join(t2,NULL);
      
              pthread_mutex_destroy(&mutex);
      
              return 0;
      }
      

  1. 条件变量:

  • 条件变量是另一种同步机制,条件本身是由互斥量保护的。线程在改变条件状态前必须首先锁住互斥量,其他线程在获得互斥量之前不会察觉到这种改变,因为必须锁定互斥量以后才能计算条件。

  1. 函数介绍
    函数名称函数作用
    pthread_cond_init
    创建条件变量
    pthread_cond_destroy
    销毁条件变量
    pthread_cond_wait
    使用该函数的线程阻塞,条件满足使用pthread_cond_signal或pthread_cond_broadcast唤醒
    pthread_cond_signal
    pthread_cond_signal函数将唤醒等待该条件的某个线程
    pthread_cond_broadcast
    pthread_cond_broadcast函数将唤醒等待该条件的所有进程
  2. 函数参数

    1. pthread_cond_init:

      1. 第一个参数为条件变量

      2. 第二个参数为属性,设置为默认属性的话为NULL

    2. pthread_cond_destroy:参数为条件变量

    3. pthread_cond_wait:

      1. 第一个参数为条件变量的地址

      2. 第二个参数为保护条件所对应的互斥锁的互斥变量的地址

    4. pthread_cond_signal和pthread_cond_broadcast:参数为条件变量

  3. 实战

    #include <stdio.h>
    #include <pthread.h>
    #include <unistd.h>
    #include <stdlib.h>
    
    pthread_mutex_t mutex;
    pthread_mutex_t mutex1;
    pthread_cond_t cond;
    int g_data = 0;
    
    void* thread1(void *arg)
    {
            static int i;
    
            printf("thread1:%ld\n",(unsigned long)pthread_self());
            printf("thread1:param = %d\n",*((int*)arg));
    
            while(1){
                    pthread_cond_wait(&cond,&mutex);
                    pthread_mutex_lock(&mutex1);
    
                    sleep(1);
                    printf("==============\n");
                    g_data = 0;
    
                    i++;
                    if(i == 6){
                            exit(0);
                    }
    
                    pthread_mutex_unlock(&mutex1);
            }
    }
    
    void* thread2(void *arg)
    {
            printf("thread2:%ld\n",(unsigned long)pthread_self());
            printf("thread2:param = %d\n",*((int*)arg));
    
            while(1){
                    pthread_mutex_lock(&mutex1);
                    pthread_mutex_lock(&mutex);
    
                    sleep(1);
    
                    printf("t2:g_data = %d\n",g_data);
    
                    g_data++;
                    if(g_data == 3){
                            pthread_cond_signal(&cond);
                    }
    
                    pthread_mutex_unlock(&mutex);
                    pthread_mutex_unlock(&mutex1);
                    sleep(2);
            }
            pthread_exit(NULL);
    }
    
    void* thread3()
    {
            printf("thread3:%ld\n",(unsigned long)pthread_self());
    
            while(1){
                    pthread_mutex_lock(&mutex1);
                    pthread_mutex_lock(&mutex);
    
                    sleep(1);
                    printf("t3:g_data = %d\n",g_data);
    
                    g_data++;
                    if(g_data == 3){
                            pthread_cond_signal(&cond);
                    }
    
                    pthread_mutex_unlock(&mutex);
                    pthread_mutex_unlock(&mutex1);
                    sleep(2);
            }
            pthread_exit(NULL);
    }
    
    int main()
    {
            pthread_t t1;
            pthread_t t2;
            pthread_t t3;
            int ret;
            int param = 100;
    
            pthread_mutex_init(&mutex,NULL);
            pthread_mutex_init(&mutex1,NULL);
            ret = pthread_cond_init(&cond,NULL);
            if(ret != 0){
                    printf("cong init error\n");
            }
    
            ret = pthread_create(&t1,NULL,thread1,(void*)&param);
            if(ret < 0){
                    printf("thread1 create error\n");
            }
    
            ret = pthread_create(&t2,NULL,thread2,(void*)&param);
            if(ret < 0){
                    printf("thread2 create error\n");
            }
    
            ret = pthread_create(&t3,NULL,thread3,NULL);
            if(ret < 0){
                    printf("thread3 create error\n");
            }
    
            pthread_join(t1,NULL);
            pthread_join(t2,NULL);
            pthread_join(t3,NULL);
            pthread_mutex_destroy(&mutex);
            pthread_mutex_destroy(&mutex1);
            pthread_cond_destroy(&cond);
    
            return 0;
    }
    

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值