现在的位置: 首页 > 综合 > 正文

线程初步(1)

2017年06月18日 ⁄ 综合 ⁄ 共 5493字 ⁄ 字号 评论关闭

线程(thread)
网络一般都需要实现代码的并行。代码的并行必须借助多进程/多线程。
进程和线程的概念
主流操作系统中都是支持多进程,而在每个进程的内部,都支持多线程并行。
进程,重量级的,拥有自己独立的内存空间。
线程,轻量级的,不需要拥有自己独立的内存空间,只是额外拥有一个独立的栈。一个进程内存的所有线程共享进程的资源(代码区、全局区、堆、文件目录......)。
因此网络开发经常是网络+多线程模式。
进程中支持多线程并行,其中有一个是主线程,进程中必须有主线程(main函数)。

计算机程序运行的硬件必备:cpu/内存,如果要并行,意味着cpu和内存都应该可分。内存可分,cpu不可分,那么多线程怎么并行?  主流操作系统采用cpu时间片技术实现多线程的并行。  人的感知是需要时间的,这种时间属于时间段,比如0.1秒,对于计算机来说,0.1秒可以分为100毫秒。把100毫秒的cpu执行时间分成100个cpu时间片,每个1毫秒。假如有4个线程并行,每个线程分一片,4毫秒以后,每个线程都运行了1毫秒。   针对时间点来说,线程没有并行;针对时间段来说,利用cpu时间片技术可以实现并行。

多线程之间互相独立,但又互相影响。
主线程一旦结束,进程随之结束,进程结束导致所有线程结束。

多线程之间代码是乱序执行,每个线程内部的代码是顺序执行。

线程的实现:
POSIX规范中对线程做了比较完善的定义,因此,线程编码使用pthread.h,几乎所有的函数都以pthread_开头。代码在libpthread.so中。比如:创建线程的函数:
pthread_create()
4个指针类型做参数,第一个参数:用于存储pthread_t类型的线程ID
第二个参数:线程属性,一般为0即可(默认属性)
第三个参数和第四个参数联合使用,第三个参数是函数指针,把线程需要执行的代码写在函数中,函数的参数由第四个参数提供。
void *(*fun) (void *)
返回,成功返回0,失败返回错误码。线程的函数错误处理通过返回错误码的方式,而不是使用errno.

pthread_join()可以让一个线程等待另外一个线程结束,并且取得结束线程的返回值。(类似wait)
在使用线程的参数时,必须保证参数的指向有效。

关于函数/线程的返回值:
1、不能直接以数组做返回类型
2、能返回局部变量
3、不能返回指向局部变量的指针
4、加了static的变量指针可以返回
线程的返回值必须是一个有效的指针。全局变量、常量、传入的指针、static的局部变量。线程的返回值可以用pthread_join的第二个参数取得。
pthread_join(pthread_t id,void **retval)取返回值时,相当于代码:
*(retval) = 线程的返回值

线程的结束:
正常的结束:
线程函数结束
pthread_exit(void *retval),与return一样
非正常结束:
出错/被其他线程取消
注:exit()结束的是进程,所以不能用于结束线程

线程的状态:
线程在启动后,可以通过不同的函数进入不同的状态:
pthread_join进入非分离状态(同步),非分离状态的线程会在pthread_join()结束后回收线程资源
pthread_detach()进入分离状态(异步),分离状态的线程会在线程结束后直接回收线程的资源。
已经处于分离状态的线程,join()没有效果。
线程最好处于这两种状态其中的一种。

线程取消(了解)
线程的取消就是给目标线程发CANCEL信号,目标线程可以作出3种选择:忽略、立刻停止、过一会再停止
线程取消的相关函数:
pthread_cancel() 给目标线程发取消信号
pthread_setcancelstate()  设置是否支持取消
pthread_setcanceltype() 设置取消的方式

线程的同步
因为多线程共享进程的资源,在访问共享的资源时,就有可能出现互相覆盖的情况,叫共享数据冲突。解决共享数据冲突的技术叫线程同步,解决方案就是把共享资源的访问代码由并行改为串行,其他代码无所谓。线程同步会降低线程的效率,因此使用时不是范围越大越好。
互斥锁/互斥量,就是其中的一种方案。我们可以在访问共享资源时加上互斥锁,访问共享资源结束后释放互斥锁,就可以把并行改为串行。确保只有一个进程访问。互斥锁是线程规范的一个组成部分。
互斥量的使用步骤:
1、声明互斥量 
pthread_mutex_t lock;
2、初始化互斥量
pthread_mutex_init(&lock,0);
或者在声明的同时初始化(注意一定要同时):
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER3、加锁
pthread_mutex_lock(&lock)
4、访问,使用,读写
5、解锁
pthread_mutex_unlock(&lock);
6、销毁锁(释放资源)
pthread_mutex_destroy(&lock);

pthread_create.c
#include<stdio.h>
#include<pthread.h>
#include<string.h>

void *task(void *p){
	int i;
	for (i = 0;i < 100;i++){
		printf("task:%d\n",i);
	}
}
int main(){
	pthread_t id;//用来存储线程ID
	printf("size=%d\n",sizeof(id));
	int res = pthread_create(&id,0,task,0);
	if (res/*!=0*/){
		printf("create error:%s\n",strerror(res));//线程错误处理
	}
	int i;
	for (i = 0;i < 100;i++){
		printf("main:%d\n",i);
	}
	sleep(1);
}
#include<stdio.h>
#include<pthread.h>

void *task(void *p){//p就是create()第4个参数
	int *pi = p;
	printf("*pi=%d\n",*pi);
	*pi = 200;
}//练习:线程传入圆的半径,打印圆的面积

void *task2(void *p){
	double *pd = p;
	printf("s=%lf\n",3.14 * (*pd) * (*pd));
}
int main(){
	pthread_t id1,id2,id3;
	int x = 100;
	pthread_create(&id1,0,task,&x);
	id2 = pthread_self();//取当前线程的ID
	printf("id1=%u,main=%u\n",id1,id2);
	pthread_join(id1,0);
	printf("x=%d\n",x);

	double d = 1.0;
	pthread_create(&id3,0,task2,&d);
	pthread_join(id3,0);
}


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

void *task(void *p){
	int x = (int)p;//可以拿指针当int用
	printf("x=%d\n",x);
}
void *task2(void *p){
	sleep(1);
	int *pi = p;//p已经被释放,无效
	printf("*pi=%d\n",*pi);
}
int main(){
	pthread_t id1,id2;
	int x = 100;
	pthread_create(&id1,0,task,(void *)x);
	pthread_join(id1,0);

	int *pi = malloc(4);
	*pi = 100;
	pthread_create(&id2,0,task2,pi);
	free(pi);
	pthread_join(id2,0);
}

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

void *task(void *p){
	printf("%s\n",(char *)p);
	p = "hello";//改地址,p指向只读常量区
	//strcpy(p,"hello");//没有改地址main()有效
	//char st[] = "hello";//局部变量,返回无效
	//return st;
	return p;//res = p;
}

//练习:在线程中计算1-10的和,并返回给main
void *task2(void *p){
	int i;
	static int s = 0;//int s = 0;
	for (i = 1;i < 11;i++){
		s = s + i;
	}
	printf("&s=%d\n",&s);
	return &s;//return (void *)s;
}

int main(){
	char str[] = "abcde";
	pthread_t id;
	pthread_create(&id,0,task,str);
	char *res;//res是野指针
	pthread_join(id,(void **)&res);//res = p;
	printf("res=%s\n",res);

	pthread_create(&id,0,task2,0);
	int *pi;
	pthread_join(id,(void **)&pi);
	printf("*pi=%d\n",*pi);
	//int x;
	//pthread_join(id,(void **)&x);//x = s
	//printf("x=%d\n",x);
}

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

void *task(void *p){
	int i;
	for(i = 0;i < 100;i++){
		if (i == 12) return (void *)i;
		//if (i == 12) pthread_exit((void *)i);
		//if (i ==  12) exit(i);//结束的是进程
	}
}
int main(){
	pthread_t id;
	pthread_create(&id,0,task,0);
	int res;
	pthread_join(id,(void **)&res);
	printf("res=%d\n",res);
	return 0;
}

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

void *task(void *p){
	int i;
	for (i = 0;i < 10;i++){
		printf("task:%d\n",i);
		usleep(100000);
	}
}
int main(){
	pthread_t id;
	pthread_create(&id,0,task,0);
	pthread_detach(id);
	pthread_join(id,0);
	int i;
	for (i = 0;i < 10;i++){
		printf("main:%d\n",i);
		usleep(100000);
	}
	return 0;
}

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

void *task1(void *p){
	//pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,0);//不能
	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,0);
    //pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,
	//		0);//立即
	pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,0);//到下一个取消点
	while(1)
		printf("******************\n"),usleep(1);
}
void *task2(void *p){
	sleep(3);
	printf("取消线程1\n");
	pthread_cancel(*(pthread_t *)p);
}
int main(){
	pthread_t id1,id2;
	pthread_create(&id1,0,task1,0);
	pthread_create(&id2,0,task2,&id1);
	pthread_join(id1,0);
	pthread_join(id2,0);
	return 0;
}

#include<stdio.h>
#include<pthread.h>
char *data[5];//数组,存储名字
int size = 0;//当前人数,数组下标
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;//1
void *task(void *p){
	pthread_mutex_lock(&lock);//2
	data[size] = (char *)p;
	sleep(1);
	size++;
	pthread_mutex_unlock(&lock);//3
}
int main(){
	data[size] = "zhangfei";
	size++;
	pthread_t id1,id2;
	pthread_create(&id1,0,task,"guanyu");
	pthread_create(&id2,0,task,"zhaoyun");
	pthread_join(id1,0);
	pthread_join(id2,0);
	pthread_mutex_destroy(&lock);//5
	int i;
	for (i = 0;i < size;i++){
		printf("%s\n",data[i]);
	}
}

抱歉!评论已关闭.