Linux程序设计--12章(线程)

 #include <pthread.h>

       int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                          void *(*start_routine) (void *), void *arg);
thread为要绑定的线程标识
attr是要创建的线程属性
start_routine是线程要执行的函数
arg是函数的参数
#include <pthread.h>

       void pthread_exit(void *retval);
retval返回的一个指向某个对象的指针

 #include <pthread.h>

       int pthread_join(pthread_t thread, void **retval);

例子:

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

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");
}

验证线程是同时执行的:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>

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;//改变run_now值,以让子线程执行
        }
        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;//改变run_now值
        }
        else {
            sleep(1);
        }
    }

    sleep(3);
}

线程同步:

1)信号量同步:
 #include <semaphore.h>

       int sem_init(sem_t *sem, int pshared, unsigned int value);
sem指定要初始化的信号
pthread为0表示是当前进程的局部信号量,否则可以在多个进程间共享
value是信号量的初值
#include <semaphore.h>

       int sem_wait(sem_t *sem);

#include <semaphore.h>

       int sem_post(sem_t *sem);
上面两个函数都是原子性的操作
wait给信号减1
post给信号加1
信号为0时调用wait的线程将等待
 #include <semaphore.h>

       int sem_destroy(sem_t *sem);
清理该信号拥有的所有资源


#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>

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以允许子线程执行
			   //如果输入过快可能子线程会执行多次
    }
    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);//将信号量减1
    while(strncmp("end", work_area, 3) != 0) {//计数
        printf("You input %d characters\n", strlen(work_area) -1);
        sem_wait(&bin_sem);
    }
    pthread_exit(NULL);
}
2)用互斥量进行同步
 #include <pthread.h>

       int pthread_mutex_init(pthread_mutex_t * mutex,
           const pthread_mutexattr_t * attr);
attr互斥量属性,默认为fast,默认值缺点:如果程序试图对一个已经加了锁的互斥量调用pthread_mutex_lock程序就会被阻塞,而因为拥有互斥量的这个线程正是现在被阻塞的线程,所以互斥量就永远不会被解锁
设置NULL使用其默认行为
#include <pthread.h>

       int pthread_mutex_lock(pthread_mutex_t *mutex);
       int pthread_mutex_unlock(pthread_mutex_t *mutex);
#include <pthread.h>

       int pthread_mutex_destroy(pthread_mutex_t *mutex);
例子:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>

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';//把首字符设为'\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);
}
这个程序保证每次输入都能被计数,但输入速度大于输出速度可能会出现不是一一对应的现象
#include <pthread.h>

       int pthread_attr_init(pthread_attr_t *attr);
       int pthread_attr_destroy(pthread_attr_t *attr);
以上两个函数初始化销毁线程属性
#include <pthread.h>

       int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
       int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);
以上两个函数设置/获取线程属性脱离状态
detachstate:
 PTHREAD_CREATE_DETACHED 不允许调用pthread_join来获得另一个线程的退出状态
 PTHREAD_CREATE_JOINABLE 允许两个线程重新合并
#include <pthread.h>

       int pthread_attr_setschedparam(pthread_attr_t *attr,
                                      const struct sched_param *param);
       int pthread_attr_getschedparam(const pthread_attr_t *attr,
                                      struct sched_param *param);
以上两个函数设置/获取线程优先级属性
可以对SCHED_OTHER策略运行的线程调度进行控制
#include <pthread.h>

       int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);
       int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy);

以上两个函数设置/获取线程优先级策略属性
SCHED_OTHER 默认属性
SCHED_FIFO 先进先出策略
SCHED_RR   循环调度机制




设置线程脱离状态例子
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>

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;//定义线程属性
	//初始化线程属性
    res = pthread_attr_init(&thread_attr);
    if (res != 0) {
        perror("Attribute creation 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);
    }
    //销毁线程属性
    (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使主线程的循环结束
    thread_finished = 1;
    pthread_exit(NULL);
}

设置线程优先级例子
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>

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);
    }
    //设置调度策略为SCHED_OTHER
    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);
    }
    //获取SCHED_OTHER最大优先级
    max_priority = sched_get_priority_max(SCHED_OTHER);
    //获取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);
}


线程取消属性
 #include <pthread.h>

       int pthread_setcancelstate(int state, int *oldstate);

       int pthread_setcanceltype(int type, int *oldtype);
state: 
PTHREAD_CANCEL_ENABLE(默认) 允许取消
PTHREAD_CANCEL_DISABLE 不允许取消
type取值:
PTHREAD_CANCEL_ASYNCHRONOUS 收到取消请求后立即采取行动
PTHREAD_CANCEL_DEFERRED(默认) 接收到取消请求后一直等待直到线程执行了以下函数之一后才采取行动
pthread_join,pthread_cond_wait,pthread_cond_timedwait,pthread_testcancel,sem_wait,sigwait
例子:


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

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");
    //向a_thread发送一个取消请求
    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 <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>

#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);//这里直接传地址过去会有问题(两个线程都有权更改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);
}

猜你喜欢

转载自blog.csdn.net/yanshaoshuai/article/details/81084911