1. 并发(concurrency):在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行。其中两种并发关系分别是同步和互斥。(并发是指同一时刻只能有一条指令执行,但多个进程指令被快速轮换执行,使得在宏观上有多个进程被同时执行的效果--宏观上并行,针对单核处理器)
2.并行(parallelism):在单处理器中多道程序设计系统中,进程被交替执行,表现出一种并发的外部特种;在多处理器系统中,进程不仅可以交替执行,而且可以重叠执行。在多处理器上的程序才可实现并行处理。从而可知,并行是针对多处理器而言的。并行是同时发生的多个并发事件,具有并发的含义,但并发不一定并行,也亦是说并发事件之间不一定要同一时刻发生。(同一时刻,有多条指令在多个处理器上同时执行--针对多核处理器)
什么是线程
Linux内核线程实现原理
类Unix系统中,早期是没有“线程”概念的,80年代才引入,借助进程机制实现出了线程的概念。因此在这类系统中,进程和线程关系密切。
三级映射:进程PCB --> 页目录(可看成数组,首地址位于PCB中) --> 页表 --> 物理页面 --> 内存单元--参考:《Linux内核源代码情景分析》 ----毛德操
线程共享资源
线程非共享资源
线程优、缺点
pthread_self函数 获取线程ID。其作用对应进程中 getpid() 函数。
pthread_create函数 创建一个新线程。 其作用,对应进程中fork() 函数。
参数:
#include
#include
#include
{printf("I'm thread, Thread ID = %lu\n", pthread_self());return NULL;
}int main(void)
{pthread_t tid;pthread_create(&tid, NULL, fun, NULL);sleep(1); // 在多线程环境中,父线程终止,全部子线程被迫终止printf("I am main, my pid = %d\n", getpid());return 0;
}
运行结果
练习:循环创建多个线程,每个线程打印自己是第几个被创建的线程。(类似于进程循环创建子进程)
#include
#include
#include
#include
{int i;i = (int)arg;//i = *((int *)arg);sleep(i); //通过i来区别每个线程printf("I'm %dth thread, Thread_ID = %lu\n", i+1, pthread_self());return NULL;
}int main(int argc, char *argv[])
{int n, i;pthread_t tid;if (argc == 2)n = atoi(argv[1]);for (i = 0; i
运行结果
线程与共享 线程间共享全局变量!
设计程序,验证线程之间共享全局数据。
#include
#include
#include
#include
{var = 200;printf("thread\n");return NULL;
}int main(void)
{printf("At first var = %d\n", var);pthread_t tid;pthread_create(&tid, NULL, tfn, NULL);sleep(1);printf("after pthread_create, var = %d\n", var);return 0;
}
运行结果
pthread_exit函数 将单个线程退出
#include
#include
#include
#include
{int i;i = (int)arg; //强转。if (i == 2)pthread_exit(NULL);sleep(i); //通过i来区别每个线程printf("I'm %dth thread, Thread_ID = %lu\n", i+1, pthread_self());return NULL;
}int main(int argc, char *argv[])
{int n , i;pthread_t tid;if (argc == 2)n = atoi(argv[1]);for (i = 0; i
运行结果
思考:使用exit将指定线程退出,可以吗? 结论:线程中,禁止使用exit函数,会导致进程内所有线程全部退出。
pthread_join函数 阻塞等待线程退出,获取线程退出状态 其作用,对应进程中 waitpid() 函数。
#include
#include
#include
#include
{int a;int b;
} exit_t;void *tfn(void *arg)
{exit_t *ret;ret = malloc(sizeof(exit_t)); // malloc分配ret->a = 100;ret->b = 300;sleep(3);//pthread_exit((void *)ret);return (void *)ret;
}int main(void)
{pthread_t tid;exit_t *retval;pthread_create(&tid, NULL, tfn, NULL);/*调用pthread_join可以获取线程的退出状态*/pthread_join(tid, (void **)&retval); //wait(&status);printf("a = %d, b = %d \n", retval->a, retval->b);return 0;
}
对比记忆:
参数 retval 非空用法
调用该函数的线程将挂起等待,直到id为thread的线程终止。thread线程以不同的方法终止,通过pthread_join得到的终止状态是不同的,总结如下:
练习:使用pthread_join函数将循环创建的多个子线程回收。
int var = 100;void *tfn(void *arg)#include
#include
#include
#include
{int i;i = (int)arg;sleep(i);if (i == 1) {var = 333;printf("var = %d\n", var);return (void *)var;}else if (i == 3) {var = 777;printf("I'm %dth pthread, pthread_id = %lu\n var = %d\n", i+1, pthread_self(), var);pthread_exit((void *)var);} else {printf("I'm %dth pthread, pthread_id = %lu\n var = %d\n", i+1, pthread_self(), var);pthread_exit((void *)var);}return NULL;
}int main(void)
{pthread_t tid[5];int i;int *ret[5]; for (i = 0; i <5; i++)pthread_create(&tid[i], NULL, tfn, (void *)i);for (i = 0; i <5; i++) {pthread_join(tid[i], (void **)&ret[i]);printf("-------%d &#39;s ret = %d\n", i, (int)ret[i]);}printf("I&#39;m main pthread tid = %lu\t var = %d\n", pthread_self(), var);sleep(i);return 0;
}
运行结果
pthread_cancel函数 杀死(取消)线程 其作用,对应进程中 kill() 函数。
#include
#include
#include
#include
{printf("thread 1 returning\n");return (void *)111;
}void *tfn2(void *arg)
{printf("thread 2 exiting\n");pthread_exit((void *)222);
}void *tfn3(void *arg)
{while (1) {printf("thread 3: I&#39;m going to die in 3 seconds ...\n");sleep(1);pthread_testcancel(); //自己添加取消点*/}return (void *)666;
}int main(void)
{pthread_t tid;void *tret = NULL;pthread_create(&tid, NULL, tfn1, NULL);pthread_join(tid, &tret);printf("thread 1 exit code = %d\n\n", (int)tret);pthread_create(&tid, NULL, tfn2, NULL); pthread_join(tid, &tret);printf("thread 2 exit code = %d\n\n", (int)tret);pthread_create(&tid, NULL, tfn3, NULL);sleep(3);pthread_cancel(tid);pthread_join(tid, &tret);printf("thread 3 exit code = %d\n", (int)tret);return 0;
}
运行结果
pthread_detach函数 实现线程分离
使用pthread_detach函数实现线程分离
void *tfn(void *arg)#include
#include
#include
#include
#include
{int n = 3;while (n--) {printf("thread count %d\n", n);sleep(1);
}return (void *)1;//pthread_exit((void *)1);
}int main(void)
{pthread_t tid;void *tret;int err;#if 1pthread_attr_t attr; /*通过线程属性来设置游离态*/pthread_attr_init(&attr);pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);pthread_create(&tid, &attr, tfn, NULL);#elsepthread_create(&tid, NULL, tfn, NULL);pthread_detach(tid); //让线程分离 ----自动退出,无系统残留资源#endifwhile (1) {err = pthread_join(tid, &tret);printf("thread exit code = %d\n", (int)tret);printf("-------------err= %d\n", err);if (err != 0)fprintf(stderr, "thread_join error: %s\n\n", strerror(err));elsefprintf(stderr, "thread exit code %d\n\n", (int)tret);sleep(1);}return 0;
}
运行结果
总结:终止某个线程而不终止整个进程,有三种方法:
进程 线程
fork pthread_create
exit pthread_exit
wait pthread_join
kill pthread_cancel
getpid pthread_self 命名空间