0-- 系列文章目录
1.进程篇: (进程篇链接)(本文章)(多线程通信篇)
2.网络篇: (文章链接)
3.数组篇: (文章链接)
4.指针篇: (文章链接)
5.内核篇: (文章链接)
6.硬件篇: (文章链接)(视频链接)
...........
1--当前文章目录
- 前言
- 一、理论部分
- 二、实际操作
- 1.创建线程(pthread_create)
- 2.线程间参数的传递(重难点
- 3.线程回收(pthread_join,多线程会有点小问题)
- 4.线程的分离(pthread_detach)
- 5.线程的取消(pthread_cancel,pthread_testcancel,pthread_setcancelstate)
- 6.线程的清理(pthread_cleanup_push)
- 7.互斥锁(pthread_rwlock_unlock,pthread_rwlock_wrlock,,pthread_mutex_lock)
- 8.死锁(两把以上会)
- 总结
一.理论部分
线程
•
进程在切换时系统开销大
•
很多操作系统引入了轻量级进程LWP
•
同一进程中的线程共享相同地址空间
•
Linux不区分进程、线程
特点
•
通常线程指的是共享相同地址(空间的多个任务)
•
使用多线程的好处(
大大提高了任务切换的效率,
避免了额外的TLB & cache的刷新)
线程(共享)资源
•可执行的指令,静态数据,进程中打开的文件描述符,
•当前工作目录,用户ID,用户组ID
线程(私有)资源
•
线程ID (TID), PC(程序计数器)和相关寄存器
•
堆栈,错误号 (errno), 优先级 执行状态和属性
Linux线程库
•pthread线程库中提供了如下基本操作
Ø
创建线程
Ø
回收线程
Ø
结束线程
•
同步和互斥机制
Ø
信号量
Ø
互斥锁
二.实际操作
1.创建线程
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
int *testThread(char *arg){
printf("zhe shi zi xian cheng,pid=%d,tid=%lu\n",getpid(),pthread_self());
return 0;
}
int main(){
pthread_t tid;
int ret;
ret = pthread_create(&tid,NULL,(void *)testThread,NULL);
printf("zhe shi zhu xian cheng\n");
sleep(1);
}
获取线程ID:两种方法
1.。。pthread_create()其中的第一个参数
2.。。在线程里面调用 pthread_self 函数
2.线程间参数的传递(重难点)
两种方式:选择使用(有报警,但是程序是可以的)
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
int *testThread(void *arg){
printf("zhe shi zi xian cheng,pid=%d,tid=%lu\n",getpid(),pthread_self());
printf("shu ru wei: %d\n", *(int *)arg); // chuan can shu
pthread_exit(NULL);
printf("after pthread exit\n");
}
int main(){
pthread_t tid;
int ret;
int arg=5;
int i;
ret = pthread_create(&tid,NULL,testThread,(void*)&arg);
printf("zhe shi zhu xian cheng,tid=%lu\n",tid);
sleep(1);
}
/*
void *testThread(void *arg){
printf("This is a thread test,pid=%d,tid=%lu\n",getpid(),pthread_self());
// return NULL;
printf("input arg=%d\n",(int)arg);
pthread_exit(NULL);
printf("after pthread exit\n");
}
int main(){
pthread_t tid;
int ret;
int arg = 5;
ret = pthread_create(&tid,NULL,testThread,(void *)arg);
printf("This is main thread,tid=%lu\n",tid);
sleep(1);
}
*/
进阶版:多线程
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
void *testThread(void *arg){
printf("This is a thread test,pid=%d,tid=%lu\n",getpid(),pthread_self());
// return NULL;
printf("This is %d thread.\n", (int)arg);
// pthread_exit(NULL);
while(1){
sleep(1);
}
printf("after pthread exit\n");
}
int main(){
pthread_t tid[5];
int ret;
int arg = 5;
int i;
for(i=0;i<5;i++){
ret = pthread_create(&tid[i],NULL,testThread,(void *)i);
// sleep(1);
printf("This is main thread,tid=%lu\n",tid[i]);
}
while(1){
sleep(1);
}
}
3.线程的回收(pthread_join,多线程会有点小问题)
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
void *func(void *arg){
printf("This is child thread\n");
sleep(25);
pthread_exit("thread return");
}
int main(){
pthread_t tid[100];
void *retv;
int i;
for(i=0;i<100;i++){
pthread_create(&tid[i],NULL,func,NULL);
}
for(i=0;i<100;i++){
// pthread_join(tid[i],&retv);
// printf("thread ret=%s\n",(char*)retv);
}
while(1){
sleep(1);
}
}
4.线程的分离(pthread_detach)
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
void *func(void *arg){
printf("This is child thread\n");
sleep(25);
pthread_exit("thread return");
}
int main(){
pthread_t tid[100];
void *retv;
int i;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
for(i=0;i<100;i++){
pthread_create(&tid[i],&attr,func,NULL);
// pthread_detach(tid);
}
while(1){
sleep(1);
}
}
用top查看,运行100个实时的内存变化
(5)线程的取消与互斥(pthread_cancel,pthread_testcancel,pthread_setcancelstate)
取消的条件:需要取消点(sleep),,或者手动添加取消点(pthread_testcancel)
取消点的选择:(pthread_setcancelstate)哪里,不能取消,哪里可以取消
创建完成后,执行线程需要时间,
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
void *func(void *arg){
printf("This is child thread\n");
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);
// while(1)
{
sleep(5);
pthread_testcancel();
}
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
while(1){
sleep(1);
}
pthread_exit("thread return");
}
int main(){
pthread_t tid;
void *retv;
int i;
pthread_create(&tid,NULL,func,NULL);
sleep(1);
pthread_cancel(tid);
pthread_join(tid,&retv);
// printf("thread ret=%s\n",(char*)retv);
while(1){
sleep(1);
}
}
(6)线程的清理(pthread_cleanup_push)
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
void cleanup(void *arg){
printf("cleanup,arg=%s\n",(char*)arg);
}
void cleanup2(void* arg){
printf("cleanup2,arg=%s\n",(char*)arg);
}
void *func(void *arg){
printf("This is child thread\n");
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
pthread_cleanup_push(cleanup,"abcd");
pthread_cleanup_push(cleanup2,"efgh");
//while(1)
{
sleep(1);
}
// pthread_cancel(pthread_self());
//printf("Should not print\n");
return "1234";
while(1){
printf("sleep\n");
sleep(1);
}
pthread_exit("thread return");
pthread_cleanup_pop(1);
pthread_cleanup_pop(1);
sleep(10);
pthread_exit("thread return");
}
int main(){
pthread_t tid;
void *retv;
int i;
pthread_create(&tid,NULL,func,NULL);
sleep(1);
// pthread_cancel(tid);
pthread_join(tid,&retv);
printf("thread ret=%s\n",(char*)retv);
while(1){
sleep(1);
}
}
(7)互斥锁(两个线程,写同一个文件的时候,排队,先后)
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
FILE *fp;
void *func2(void *arg){
pthread_detach(pthread_self());
printf("This func2 thread\n");
char str[]="I write func2 line\n";
char c;
int i=0;
while(1){
pthread_mutex_lock(&mutex);
while(i<strlen(str))
{
c = str[i];
fputc(c,fp);
usleep(1);
i++;
}
pthread_mutex_unlock(&mutex);
i=0;
usleep(1);
}
pthread_exit("func2 exit");
}
void *func(void *arg){
pthread_detach(pthread_self());
printf("This is func1 thread\n");
char str[]="You read func1 thread\n";
char c;
int i=0;
while(1){
pthread_mutex_lock(&mutex);
while(i<strlen(str))
{
c = str[i];
fputc(c,fp);
i++;
usleep(1);
}
pthread_mutex_unlock(&mutex);
i=0;
usleep(1);
}
pthread_exit("func1 exit");
}
int main(){
pthread_t tid,tid2;
void *retv;
int i;
fp = fopen("1.txt","a+");
if(fp==NULL){
perror("fopen");
return 0;
}
pthread_create(&tid,NULL,func,NULL);
pthread_create(&tid2,NULL,func2,NULL);
while(1){
sleep(1);
}
}
读取的锁,可以多个读取,写的时候阻塞
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
pthread_rwlock_t rwlock;
FILE *fp;
void * read_func(void *arg){
pthread_detach(pthread_self());
printf("read thread\n");
char buf[32]={0};
while(1){
//rewind(fp);
pthread_rwlock_rdlock(&rwlock);
while(fgets(buf,32,fp)!=NULL){
printf("%d,rd=%s\n",(int)arg,buf);
usleep(1000);
}
pthread_rwlock_unlock(&rwlock);
sleep(1);
}
}
void *func2(void *arg){
pthread_detach(pthread_self());
printf("This func2 thread\n");
char str[]="I write func2 line\n";
char c;
int i=0;
while(1){
pthread_rwlock_wrlock(&rwlock);
while(i<strlen(str))
{
c = str[i];
fputc(c,fp);
usleep(1);
i++;
}
pthread_rwlock_unlock(&rwlock);
i=0;
usleep(1);
}
pthread_exit("func2 exit");
}
void *func(void *arg){
pthread_detach(pthread_self());
printf("This is func1 thread\n");
char str[]="You read func1 thread\n";
char c;
int i=0;
while(1){
pthread_rwlock_wrlock(&rwlock);
while(i<strlen(str))
{
c = str[i];
fputc(c,fp);
i++;
usleep(1);
}
pthread_rwlock_unlock(&rwlock);
i=0;
usleep(1);
}
pthread_exit("func1 exit");
}
int main(){
pthread_t tid1,tid2,tid3,tid4;
void *retv;
int i;
fp = fopen("1.txt","a+");
if(fp==NULL){
perror("fopen");
return 0;
}
pthread_rwlock_init(&rwlock,NULL);
pthread_create(&tid1,NULL,read_func,1);
pthread_create(&tid2,NULL,read_func,2);
pthread_create(&tid3,NULL,func,NULL);
pthread_create(&tid4,NULL,func2,NULL);
while(1){
sleep(1);
}
}
(8)死锁
概念:
避免方法:
- 锁越少越好,最好使用一把锁
- 调整好锁的顺序
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
FILE *fp;
void *func2(void *arg){
pthread_detach(pthread_self());
printf("This func2 thread\n");
char str[]="I write func2 line\n";
char c;
int i=0;
while(1){
pthread_mutex_lock(&mutex);
printf("%d,I got lock2\n",(int)arg);
sleep(1);
pthread_mutex_lock(&mutex2);
printf("%d,I got 2 locks\n",(int)arg);
pthread_mutex_unlock(&mutex2);
pthread_mutex_unlock(&mutex1);
sleep(10);
}
pthread_exit("func2 exit");
}
void *func(void *arg){
pthread_detach(pthread_self());
printf("This is func1 thread\n");
char str[]="You read func1 thread\n";
char c;
int i=0;
while(1){
pthread_mutex_lock(&mutex);
printf("%d,I got lock1\n",(int)arg);
sleep(1);
pthread_mutex_lock(&mutex2);
printf("%d,I got 2 locks\n",(int)arg);
pthread_mutex_unlock(&mutex2);
pthread_mutex_unlock(&mutex);
sleep(10);
}
pthread_exit("func1 exit");
}
int main(){
pthread_t tid,tid2;
void *retv;
int i;
fp = fopen("1.txt","a+");
if(fp==NULL){
perror("fopen");
return 0;
}
pthread_create(&tid,NULL,func,1);
pthread_create(&tid2,NULL,func2,2);
while(1){
sleep(1);
}
}