linux——线程

线程的概念:
线程是进程内部的一条执行序列(执行流), 每个进程至少有一条执行序列:
main的执行体。

进程可以通过线程库创建N条线程, 这些新创建的线程称之为函数线程,main函数所代表的线程为主线程。

线程是一个更加接近于执行体的概念,它可以与同进程中的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。在串行程序基础上引入线程和进程是为了提高程序的并发度,从而提高程序运行效率和响应时间。


线程与进程的区别:
1、 进程是资源分配的最小单位, 线程是CPU调度的最小单位
2、 线程是轻量级的进程
3、 管理方式不同, 进程是PCB管理, 线程是由线程结构管理。


线程和进程在使用上各有优缺点:

 线程执行开销小,但不利于资源的管理和保护;而进程正相反。同时,线程适合于在SMP机器上运行,而进程则可以跨机器迁移。


用户级
内核级
混合模式


线程的创建:(线程库文件的使用)pthread
int pthread_create(pthread_t *id,   pthread_attr_t *attr,  void* (*fun)(void*),   void *arg);
创建一个函数线程!

与fork()调用创建一个进程的方法不同,pthread_create()创建的线程并不具备与主线程(即调用pthread_create()的线程)同样的执行序列,而是使其运行start_routine(arg)函数。thread返回创建的线程ID,而attr是创建线程时设置的线程属性(见下)。pthread_create()的返回值表示线程创建是否成功。尽管arg是void *类型的变量,但它同样可以作为任意类型的参数传给start_routine()函数;同时,start_routine()可以返回一个void *类型的返回值,而这个返回值也可以是其他类型,并由pthread_join()获取
包含线程创建函数的源代码要想生成可执行文件, 必须::
gcc -o pthread pthread.c-lpthread
创建出来的函数线程不同于函数调用, 函数调用是这条执行流中的一部分。

#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
//#include<fcntl.h>
//#include<ctype.h>
#include<pthread.h>
#include<semaphore.h>

void*pthread_fun(void*arg)
{
	char buff[128]="a b c d e f g h";
	char *q=NULL;
	char *p=strtok_r(buff," ",&q);
	while(p!=NULL)
	{
		printf("fun::%s\n",p);
		sleep(1);
		p=strtok_r(NULL," ",&q);
	}
}
void main()
{
    pthread_t id;
	int res=pthread_create(&id,NULL,pthread_fun,NULL);
    assert(res==0);
	int count=0;
		
	char buff[128]="0 1 2 3 4 5 6 7";
	char *q=NULL;
	char *p=strtok_r(buff," ",&q);
	while(p!=NULL)
	{
		printf("main::%s\n",p);
		sleep(1);
		p=strtok_r(NULL," ",&q);
	}
}

函数线程是创建出一条独立的执行序列, 他与主线程同时执行。
线程结束:
int pthread_exit(void *);参数可以设置线程结束状态
等待线程结束:
int pthread_join(pthread_t id, void **);
可以获取到等待的线程通过pthread_exit设置的结束状态信息
线程函数传参:
1、 将值强转成void*
int a = (int) arg;
2
、 将地址强转成void*
int a = *(int*)arg;

1、 线程同步
同步: 多进程或者多线程访问临界资源时, 必须进行同步控制。 多进程或者多线
程的执行并不完全是绝对的并行运行,有可能主线程需要等待函数线程的某些条件的发
生。
多线程之间有几个特殊的临界资源:
全局数据、 堆区数据、 文件描述符 多线程之间共用
线程间同步控制方式:
1.1信号量#include <semaphore.h>
获取:int sem_init(sem_t *sem, int shared , int value);
sem:
是一个sem_t类型指针, 指向信号量对象。
shared:是否能在多进程间共享,Linux不支持, 0
value:
信号量的初始值
返回值:
0成功-1失败
P操作:int sem_wait(sem_t *sem); //阻塞运行
V操作:int sem_post(sem_t *sem);
删除:int sem_destroy(sem_t *sem);
互斥锁
概念: 完全控制临界资源, 如果一个线程完成加锁操作, 则其他线程无论如何
都无法再完成加锁, 也就无法对临界资源进行访问。
初始化:
int pthread_mutex_init(pthread_mutex_t *mutex,
pthread_mutex_attr_t *attr);
加锁:int pthread_mutex_lock(pthread_mutex_t *mutex); //阻塞运行
int pthread_mutex_trylock(pthread_mutex_t *mutex); //非阻塞版本
解锁:
int pthread_mutex_unlock(pthread_mutex_t *mutex);
释放:int pthread_mutex_destroy(pthread_mutex_t *mutex);
1.3
条件变量
2、 线程安全--->可重入函数
有些库函数会使用线程间共享的数据, 如果没有同步控制, 线程操作就是不安全的,
所以, 我们使用这样一些函数时, 就必须使用其安全的版本
---》 可重入函数



线程中 fork的使用, 锁的变化
在线程中调用
fork函数, 子进程只会启用调用fork函数的那条线程, 其他线程 不
会启用。
子进程会继承其父进程的锁以及锁的状态, 但是
父子进程用的不是同一把锁, 父进
程解锁并不会影响到子进程的锁, 所以
子进程有可能死锁!!!
pthread_atfork(void (*prepare)(void), void (*parent)(void ), void (*child)(void));
指定在fork调用之后, 创建子进程之前, 调用prepare函数, 获取所有的锁,
然后创建子进程, 子进程创建以后, 父进程环境中调用
parent解所有的锁, 子进
程环境中调用
child解所有的锁, 然后fork函数再返回。 这样保证了fork之后, 子进程
拿到的锁都是解锁状态, 避免死锁。

练习  :统计end前几个单词

#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
//#include<ctype.h>
//#include<fcntl.h>
#include<semaphore.h>
#include<pthread.h>

char buff[128]={0};
sem_t sem;
pthread_mutex_t mutex;
void *pthread_fun(void*arg)
{
   while(1)
   {
      if(strncmp(buff,"end",3)==0)
	  {
           break;  
	  }
   }
	  printf("%d\n",strlen(buff)-1);
	  pthread_mutex_unlock(&mutex);
	  sleep(1);
   
}

void main()
{
//	sem_init(&sem,0,0);
	pthread_mutex_init(&mutex,NULL);
    pthread_t id;
	int res = pthread_create(&id,NULL,pthread_fun,NULL);
	assert(res==0);
	while(1)
	{
		pthread_mutex_lock(&mutex);
    	printf("please input:");
	    fflush(stdout);
//	char buff[128]={0};
	    fgets(buff,128,stdin);
    	pthread_mutex_unlock(&mutex);
		sleep(1);
	//sem_post(&sem);
	if(strncmp(buff,"end",3)==0)
	{
		break;
	}
}
   
  pthread_join(id,NULL);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值