linux系统——POSIX线程模型

一、线程基础

1、定义:
当在进程中创建一个新的线程时,新执行线程将拥有自己栈空间隐刺也有自己的局部变量),但是它与创建者共享全局变量、文件描述符、信号处理函数和当前的目录状态
2、优点:
3、缺点:
4、线程有一套完整的与其有关额函数库,它们中大多数函数名都以pthread_开头,为了使用这些函数库,必须定义宏_REENTRANT,头文件为pthread.h,编译程序额时候用选项-lpthread来链接线程库

二、线程函数

1、创建线程



2、退出线程

linux系统——POSIX线程模型_第1张图片

3、等待线程

linux系统——POSIX线程模型_第2张图片

4、线程简单例子:

例子char message[]主线程和子线程共享的变量

#include 
#include 
#include 
#include 
#include 

void *thread_function(void *arg);

char message[] = "Hello World";

int main() {
    int res;
    pthread_t a_thread;
    void *thread_result;
    res = pthread_create(&a_thread, NULL, thread_function, (void *)message);
    if (res != 0) {
        perror("Thread creation failed");
        exit(EXIT_FAILURE);
    }
    printf("Waiting for thread to finish...\n");
    res = pthread_join(a_thread, &thread_result);
    if (res != 0) {
        perror("Thread join failed");
        exit(EXIT_FAILURE);
    }
    printf("Thread joined, it returned %s\n", (char *)thread_result);
    printf("Message is now %s\n", message);
    exit(EXIT_SUCCESS);
}

void *thread_function(void *arg) {
    printf("thread_function is running. Argument was %s\n", (char *)arg);
    sleep(3);
    strcpy(message, "Bye!");
    pthread_exit("Thank you for the CPU time");
}

三、线程同步

1、变量条件同步:

子线程创建后,父子线程是通过CPU在线程快速切换来完成“看起来像是同时执行”的动作,除了线程局部变量外,所有其他的变量都将在一个进程中的所有线程间共享,例子如下:

#include 
#include 
#include 
#include 

void *thread_function(void *arg);
int run_now = 1;
char message[] = "Hello World";

int main() {
    int res;
    pthread_t a_thread;
    void *thread_result;
    int print_count1 = 0;

    res = pthread_create(&a_thread, NULL, thread_function, (void *)message);
    if (res != 0) {
        perror("Thread creation failed");
        exit(EXIT_FAILURE);
    }

    while(print_count1++ < 20) {
        if (run_now == 1) {
            printf("1");
            run_now = 2;
        }
        else {
            sleep(1);
        }
    }

    printf("\nWaiting for thread to finish...\n");
    res = pthread_join(a_thread, &thread_result);
    if (res != 0) {
        perror("Thread join failed");
        exit(EXIT_FAILURE);
    }
    printf("Thread joined\n");
    exit(EXIT_SUCCESS);
}

void *thread_function(void *arg) {
    int print_count2 = 0;

    while(print_count2++ < 20) {
        if (run_now == 2) {
            printf("2");
            run_now = 1;
        }
        else {
            sleep(1);
        }
    }

    sleep(3);
}

2、计数信号量同步

计数信号量:有更多的取值
linux系统——POSIX线程模型_第3张图片
linux系统——POSIX线程模型_第4张图片

计数信号量同步例子:

#include 
#include 
#include 
#include 
#include 
#include 

void *thread_function(void *arg);
sem_t bin_sem;

#define WORK_SIZE 1024
char work_area[WORK_SIZE];

int main() {
    int res;
    pthread_t a_thread;
    void *thread_result;

    res = sem_init(&bin_sem, 0, 0);
    if (res != 0) {
        perror("Semaphore initialization failed");
        exit(EXIT_FAILURE);
    }
    res = pthread_create(&a_thread, NULL, thread_function, NULL);
    if (res != 0) {
        perror("Thread creation failed");
        exit(EXIT_FAILURE);
    }
    printf("Input some text. Enter 'end' to finish\n");
    while(strncmp("end", work_area, 3) != 0) {
        fgets(work_area, WORK_SIZE, stdin);
        sem_post(&bin_sem);//信号量+1表示,共享变量可操作
    }
    /*以下可应对:连续快速的给出两组数据而导致的子线程没有时间处理,信号量的逻辑运算错误问题/*
    /*
   while(strncmp("end", work_area, 3) != 0) {
      if (strncmp(work_area, "FAST", 4) == 0) {
        sem_post(&bin_sem);
        strcpy(work_area, "Wheeee...");
      } else {
        fgets(work_area, WORK_SIZE, stdin);
    }
    */  
      sem_post(&bin_sem);
    }
    printf("\nWaiting for thread to finish...\n");
    res = pthread_join(a_thread, &thread_result);
    if (res != 0) {
        perror("Thread join failed");
        exit(EXIT_FAILURE);
    }
    printf("Thread joined\n");
    sem_destroy(&bin_sem);
    exit(EXIT_SUCCESS);
}

void *thread_function(void *arg) {
    sem_wait(&bin_sem);//线程阻塞,直到信号量不为0
    while(strncmp("end", work_area, 3) != 0) {
        printf("You input %d characters\n", strlen(work_area) -1);
        sem_wait(&bin_sem);//线程阻塞,直到信号量不为0
    }
    pthread_exit(NULL);
}

补充说明:
在这里插入图片描述
以上程序是有缺陷的,应考虑主线程连续快速的给出两组数据而导致的子线程没有时间处理,信号量的逻辑运算错误问题

3、互斥信号量同步

二值信号量:只有0-1取值
函数:
linux系统——POSIX线程模型_第5张图片
互斥信号量例子:

#include 
#include 
#include 
#include 
#include 
#include 

void *thread_function(void *arg);
pthread_mutex_t work_mutex; /* protects both work_area and time_to_exit */

#define WORK_SIZE 1024
char work_area[WORK_SIZE];
int time_to_exit = 0;

int main() {
    int res;
    pthread_t a_thread;
    void *thread_result;
    res = pthread_mutex_init(&work_mutex, NULL);
    if (res != 0) {
        perror("Mutex initialization failed");
        exit(EXIT_FAILURE);
    }
    res = pthread_create(&a_thread, NULL, thread_function, NULL);
    if (res != 0) {
        perror("Thread creation failed");
        exit(EXIT_FAILURE);
    }
    pthread_mutex_lock(&work_mutex);
    printf("Input some text. Enter 'end' to finish\n");
    while(!time_to_exit) {
        fgets(work_area, WORK_SIZE, stdin);
        pthread_mutex_unlock(&work_mutex);
        while(1) {
            pthread_mutex_lock(&work_mutex);
            if (work_area[0] != '\0') {
                pthread_mutex_unlock(&work_mutex);
                sleep(1);
            }
            else {
                break;
            }
        }
    }
    pthread_mutex_unlock(&work_mutex);
    printf("\nWaiting for thread to finish...\n");
    res = pthread_join(a_thread, &thread_result);
    if (res != 0) {
        perror("Thread join failed");
        exit(EXIT_FAILURE);
    }
    printf("Thread joined\n");
    pthread_mutex_destroy(&work_mutex);
    exit(EXIT_SUCCESS);
}

void *thread_function(void *arg) {
    sleep(1);
    pthread_mutex_lock(&work_mutex);//新线程试图加锁,如果锁已被锁住,则阻塞直到锁被释放
    while(strncmp("end", work_area, 3) != 0) {
        printf("You input %d characters\n", strlen(work_area) -1);
        work_area[0] = '\0';
        pthread_mutex_unlock(&work_mutex);
        sleep(1);//解锁后等待主线程运行
        pthread_mutex_lock(&work_mutex);//试图加锁,如果锁已被锁住,则阻塞直到锁被释放
        while (work_area[0] == '\0' ) {
            pthread_mutex_unlock(&work_mutex);
            sleep(1);
            pthread_mutex_lock(&work_mutex);
        }
    }
    time_to_exit = 1;//有申请退出程序的请求,置标志
    work_area[0] = '\0';
    pthread_mutex_unlock(&work_mutex);
    pthread_exit(0);
}

四、线程属性

线程属性作用于如下 :在这里插入图片描述

1、脱线线程

假设我们在主线程继续为用户提供服务的同时创建了第二个线程,新线程的作用是将用户正在编辑的数据文件进行备份存贮,备份工作技术后,第二个线程就可以直接终止了,它没必要再回到主线程中,此时我们就可以创建脱线线程

2、线程属性设置函数

linux系统——POSIX线程模型_第6张图片linux系统——POSIX线程模型_第7张图片linux系统——POSIX线程模型_第8张图片

3、线程属性例子——脱线属性、线程调度策略

->该例子中,子线程是脱线线程,开始后独立结束,并没有返回线程状态给主线程
->调度策略设置后,需要设置调度策略参数,该策略决定谁获取cpu的执行权重比例

#include 
#include 
#include 
#include 

void *thread_function(void *arg);

char message[] = "Hello World";
int thread_finished = 0;

int main() {
    int res;
    pthread_t a_thread;
    void *thread_result;
    pthread_attr_t thread_attr;

    **int max_priority;
    int min_priority;
    struct sched_param scheduling_value;**

    res = pthread_attr_init(&thread_attr);//初始化线程属性对象
    if (res != 0) {
        perror("Attribute creation failed");
        exit(EXIT_FAILURE);
    }
    res = pthread_attr_setschedpolicy(&thread_attr, SCHED_OTHER);//设置线程调度策略
    if (res != 0) {
        perror("Setting schedpolicy failed");
        exit(EXIT_FAILURE);
    }
    res = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);//设置线程脱线属性
    if (res != 0) {
        perror("Setting detached attribute failed");
        exit(EXIT_FAILURE);
    }
    res = pthread_create(&a_thread, &thread_attr, thread_function, (void *)message);//创建线程
    if (res != 0) {
        perror("Thread creation failed");
        exit(EXIT_FAILURE);
    }
    max_priority = sched_get_priority_max(SCHED_OTHER);//获取可用的最大优先级级别
    min_priority = sched_get_priority_min(SCHED_OTHER);//获取可用的最小优先级级别
    scheduling_value.sched_priority = min_priority;
    res = pthread_attr_setschedparam(&thread_attr, &scheduling_value);//设置调度参数
    if (res != 0) {
        perror("Setting schedpolicy failed");
        exit(EXIT_FAILURE);
    }
    (void)pthread_attr_destroy(&thread_attr);//销毁线程属性对象
    while(!thread_finished) {
        printf("Waiting for thread to say it's finished...\n");
        sleep(1);
    }
    printf("Other thread finished, bye!\n");
    exit(EXIT_SUCCESS);
}

void *thread_function(void *arg) {
    printf("thread_function is running. Argument was %s\n", (char *)arg);
    sleep(4);
    printf("Second thread setting finished flag, and exiting now\n");
    thread_finished = 1;
    pthread_exit(NULL);
}

五、取消线程

1、取消线程对象相关函数

linux系统——POSIX线程模型_第9张图片linux系统——POSIX线程模型_第10张图片2、取消线程对象例子

#include 
#include 
#include 
#include 

void *thread_function(void *arg);

int main() {
    int res;
    pthread_t a_thread;
    void *thread_result;

    res = pthread_create(&a_thread, NULL, thread_function, NULL);
    if (res != 0) {
        perror("Thread creation failed");
        exit(EXIT_FAILURE);
    }
    sleep(3);
    printf("Canceling thread...\n");
    **res = pthread_cancel(a_thread);//主线程内取消子线程**
    if (res != 0) {
        perror("Thread cancelation failed");
        exit(EXIT_FAILURE);
    }
    printf("Waiting for thread to finish...\n");
    res = pthread_join(a_thread, &thread_result);
    if (res != 0) {
        perror("Thread join failed");
        exit(EXIT_FAILURE);
    }
    exit(EXIT_SUCCESS);
}

void *thread_function(void *arg) {
    int i, res, j;
    **res = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);//设置子线程被取消使**能位
    if (res != 0) {
        perror("Thread pthread_setcancelstate failed");
        exit(EXIT_FAILURE);
    }
    **res = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);//设置子线程被取消的时候的动作类型**
    if (res != 0) {
        perror("Thread pthread_setcanceltype failed");
        exit(EXIT_FAILURE);
    }
    printf("thread_function is running\n");
    for(i = 0; i < 10; i++) {
        printf("Thread is still running (%d)...\n", i);
        sleep(1);
    }
    pthread_exit(0);
}

六、多线程

#include 
#include 
#include 
#include 
#include 

#define NUM_THREADS 6

void *thread_function(void *arg);

int main() {
  
  int res;
  pthread_t a_thread[NUM_THREADS];
  void *thread_result;
  int lots_of_threads;
  

  for(lots_of_threads = 0; lots_of_threads < NUM_THREADS; lots_of_threads++) {

    res = pthread_create(&(a_thread[lots_of_threads]), NULL, thread_function, (void *)lots_of_threads);
    if (res != 0) {
      perror("Thread creation failed");
      exit(EXIT_FAILURE);
    }
    /*    sleep(1); */
  }

  printf("Waiting for threads to finish...\n");
  for(lots_of_threads = NUM_THREADS - 1; lots_of_threads >= 0; lots_of_threads--) {
    res = pthread_join(a_thread[lots_of_threads], &thread_result);
    if (res == 0) {
      printf("Picked up a thread\n");
    } else {
      perror("pthread_join failed");
    }
  }

  printf("All done\n");
  
  exit(EXIT_SUCCESS);
}

void *thread_function(void *arg) {
    int my_number = (int)arg;
    int rand_num;

    printf("thread_function is running. Argument was %d\n", my_number);
    rand_num=1+(int)(9.0*rand()/(RAND_MAX+1.0));
    sleep(rand_num);
    printf("Bye from %d\n", my_number);
    
    pthread_exit(NULL);
}

你可能感兴趣的:(linux,c)