一、多线程 VS 多进程
和进程相比,线程有很多优势。在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护代码段和数据。而运行于一个进程中的多个线程,他们之间使用相同的地址空间。正是这样,同一进程下的线程之间共享数据空间,数据可以相互使用,并且线程间切换也要更快些,可以更有效的利用CPU。
二、程序设计
[注] 头文件<pthread.h> 编译时要加载动态库 libpthread.a,使用 -lpthread
 
1、创建线程
2、等待线程
3、关闭线程
4、退出清除
 
1、创建线程
复制代码代码如下:
         int pthread_create(pthread_t *tidp, const pthread_attr_t *attr, void *(*start_rtn)(void), void *arg)
tidp为线程id,是函数分配的值,所以要传一个 pthread_t 的地址。
attr线程属性,通常为空。
start_rtn为线程要执行的函数,返回值为空指针,参数为后面的*arg
若成功则返回0,否则返回出错编号。
 
例:
复制代码代码如下:
#include<stdio.h>
#include<pthread.h></p>
<p>void *func1(void *arg){        //原函数声明
        int i;
        for(i=0;i<5;i++){
                printf("this is func1! The num is %d\n",*(int*)arg);    //将空指针转换为int型指针
                sleep(1);
        }
}</p>
<p>void *func2(int *m){ //自定义类型声明,也可以定义非指针类型,但是在create时会有警告,因为非地址并不能改变传入的值
        int i;
        for(i=0;i<5;i++){
                printf("this is func2! The num is %d\n",*m);
                (*m)++;
                sleep(1);
        }
}</p>
<p>int main(){
        pthread_t id1,id2;
        int num = 5;
        int *p = #
        if(pthread_create(&id1,NULL,(void *)func1,(void *)p) != 0){
                printf("thread1 create error!\n");
                return -1;
        }
        if(pthread_create(&id2,NULL,(void *)func2,&num) != 0){
                printf("thread2 create error!\n");
                return -1;
        }
        pthread_join(id1,NULL);     //等待线程结束   
        pthread_join(id2,NULL);
        printf("Running complete!\n");
        return 0;</p>
<p>
}
运行结果:
复制代码代码如下:
[fsy@localhost process]$ gcc thC.c -o thC -lpthread -g
[fsy@localhost process]$ ./thC
this is func2! The num is 5
this is func1! The num is 6
this is func2! The num is 6
this is func1! The num is 7
this is func2! The num is 7
this is func1! The num is 8
this is func2! The num is 8
this is func1! The num is 9
this is func2! The num is 9
this is func1! The num is 10
Running complete!
[fsy@localhost process]$
2、等待线程
[注]当调用pthread_create函数时,线程并没有开始执行,主进程应有等待,比如用sleep,或者用更专业的函数:pthread_join
复制代码代码如下:
    int pthread_join(pthread_t tid, void **rval_ptr)
 
调用函数可以阻塞调用线程,直到指定的线程终止。
tid为等待退出线程的id,rval_ptr为函数的返回值。是指向指针的指针,可以置空。
 
例:
复制代码代码如下:
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h></p>
<p>void *func(int *p){
        int *num=(int *)malloc(sizeof(int));     //必须动态创建,原因可以参考我动态分配内存的博客
        printf("Please input the number: ");
        scanf("%d",num);
        return (void *)num;              //类型是pthread_create的参数规定的
}</p>
<p>int main(){
        pthread_t pth;
        void *a;
        if(pthread_create(&pth,NULL,(void *)func,NULL) != 0){
                printf("create thread error!\n");
                return 1;
        }
        pthread_join(pth,&a);          //指向空指针的指针
        printf("get the num from the thread, it's %d\n",*(int *)a);
        return 0;
}
3、终止线程
线程终止有以下三种方式:
1、线程从函数中返回
2、线程可以别其他函数终止
3、线程自己调用pthread_exit函数
复制代码代码如下:
void pthread_exit(void *rval_ptr)
rval_ptr为线程退出返回值的指针,即函数返回值。
4、退出清除
复制代码代码如下:
       void pthread_cleanup_push(void (*rtn)(void*), void *arg)
rtn为清除函数,arg是清除函数的参数
复制代码代码如下:
void pthread_cleanup_pop(int execute)
当execute 非0时执行清除函数。为0时不执行。
从pthread_cleanup_push的调用点到pthread_cleanup_pop之间的程序段中,如果有终止进程的动作,如调用pthread_exit或异常终止(不包括return),就会执行pthread_cleanup_push()所指定的清理函数。多个嵌套匹配时,就近匹配。
 
例:
复制代码代码如下:
#include<stdio.h>
#include<pthread.h></p>
<p>void *clean(char *argv){
        printf("clean is called by %s\n",argv);
        return NULL;
}
void *func1(void *argv){
        printf("welcome enter the func1!\n");
        pthread_cleanup_push((void*)clean,"the first time call!");
        pthread_cleanup_push((void*)clean,"the second time call!");
        if(argv){
                return (void *)1;            //第二次运行将此句注掉
        }
        pthread_cleanup_pop(0);
        pthread_cleanup_pop(1);
        return (void *)0;
}</p>
<p>void *func2(void *argv){
        sleep(1);             //两个线程运行先后不确定
        printf("welcome enter the func2!\n");
        pthread_cleanup_push((void*)clean,"the first time call!");
        pthread_cleanup_push((void*)clean,"the second time call!");
        if(argv){
                pthread_exit(NULL);
        }
        pthread_cleanup_pop(0);
        pthread_cleanup_pop(0);
        return (void *)0;
}</p>
<p>
int main(){
        pthread_t tid1,tid2;
        if(pthread_create(&tid1,NULL,(void *)func1,(void *)1) != 0){
                printf("thread1 create error!\n");
                return 1;
        }</p>
<p>         if(pthread_create(&tid2,NULL,(void *)func2,(void *)1) != 0){
                printf("thread2 create error!\n");
                return 1;
        }
        pthread_join(tid1,NULL);
        pthread_join(tid2,NULL);
        return 0;
}
运行结果:
复制代码代码如下:
[fsy@localhost process]$ gcc thClean.c -o thclean -lpthread
[fsy@localhost process]$ ./thclean
welcome enter the func1!
welcome enter the func2!
clean is called by the second time call!          //此处先2后1
clean is called by the first time call!
[fsy@localhost process]$ vim thClean.c
[fsy@localhost process]$ gcc thClean.c -o thclean -lpthread
[fsy@localhost process]$ ./thclean
welcome enter the func1!
clean is called by the first time call!          //second已经被pop
welcome enter the func2!
clean is called by the second time call!
clean is called by the first time call!
[fsy@localhost process]$ 
Linux,多线程,编程实例
稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!
昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。
这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。
而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?
更新动态
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
 - 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
 - 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
 - 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
 - 群星《2024好听新歌42》AI调整音效【WAV分轨】
 - 王思雨-《思念陪着鸿雁飞》WAV
 - 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
 - 李健《无时无刻》[WAV+CUE][590M]
 - 陈奕迅《酝酿》[WAV分轨][502M]
 - 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
 - 群星《吉他王(黑胶CD)》[WAV+CUE]
 - 齐秦《穿乐(穿越)》[WAV+CUE]
 - 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
 - 邝美云《邝美云精装歌集》[DSF][1.6G]
 - 吕方《爱一回伤一回》[WAV+CUE][454M]