线程相关知识点

文章目录


前言

        进程是系统中程序执行和资源分配的基本单位。每个进程都有自己的数据段、代码段和堆栈段,这就造成了程序在进行切换时操作系统的开销比较大。为了提高效率,操作系统有引入了另一个概念——线程,也称为轻量级进程。

一、线程

进程特点:

1、每一个进程之间的地址空间是相互独立的;

2、每一个进程都有一个task_struct任务结构体;

3、在进行进程切换时,需要不断刷新cache缓存,比较消耗资源;

4、为了减少cache舒心是的资源消耗,引入轻量级进程------线程。

线程特点:

1、同一个进程创建的多个线程,共用同一个进程的地址空间;

2、进程创建线程后,我们把原本进程也可以称为线程,称为主线程。

进程被称为是最小的资源分配单位;

线程被称为CPU最小的任务调度单位。

线程公共数据:用户名、用户组名、静态数据、全局数据、文件描述符;

线程私有数据:线程ID、pc、优先级、状态、属性、堆栈。

二、线程相关接口函数

1.pthread_create----创建线程

 #include <pthread.h>

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
参数:
    thread:表示线程对象,一个线程对应一个线程对象;
    attr:线程属性,填NULL表示使用默认属性(结合属性);
    start_routine:表示线程处理函数(回调函数)自己创建void *(*start_routine) (void *)---函数指针;
    arg:给线程处理函数start_routine传参数(void *表示最大可以有一个),如果线程处理函数没有参数,则填NULL。
    
返回值:
    成功返回0,失败返回错误编号。
在编译跟线程操作相关的程序时,需要链接线程    线程库的库名---pthread

 代码如下(示例):

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

int main()
{
    ptread_t pthread1;
    int ret = pthread_create(&pthread1,NULL,func,NULL);//创建线程
    if(ret < 0)
    {
        perror("pthread_create");//创建失败
        exit(-1);
    }


 

2.pthread_exit------结束线程 

#include <pthread.h>

       void pthread_exit(void *retval);
参数:
    retval:表示线程结束信息,由pthead_join等待接收,不想返回信息填NULL 。
        返回值---return value

3.pthread_join------等待线程

#include <pthread.h>

int pthread_join(pthread_t thread, void **retval);
等待线程一般在主线程中调用

三、线程间的通信

线程间的通信只需要利用全局变量就可以实现。

在一个线程使用全局变量时,有可能其他线程也在访问该数据,那么某一线程视同的数据就可能遭到破坏

通过线程的同步和互斥,能够达到数据保护的效果

(1)同步:多个线程之间按照事先约定好的顺序,有先后的完成某个事件

信号量:是系统中的一种资源,本质是一个非负整数,信号量的值等于资源的个

 操作信号量只能由特定函数接口才能访问 :

1.信息量的初始化----sem_init()

#include <semaphore.h>

  int sem_init(sem_t *sem, int pshared, unsigned int value);
参数:
    sem:信行量对象
    pshared:填0表示用于线程间同步
    value:信号量的初始值
返回值:
    成功返回0,失败返回-1;

2.P操作(申请资源)------sem_wait()

         如果有可用资源(信号量值大于0),则占用一个资源(信号量值减一,进入临界区代码);如果没有可用资源(信号量值等于0),则被阻塞,直到系统将资源分配给该任务(进入等待队列,一直等到有资源则被唤醒)。

#include <semaphore.h>

   int sem_wait(sem_t *sem);
参数:
    sem:信号量对象

执行过程:

if(是否有资源)
{
        执行后序代码;
        信号量减一;
}
else
{
    阻塞等待,知道有资源唤醒为止;
}

3.V操作(释放资源)-----sem_post() 

        如果在该信号量的等待队列中有任务在等待资源,则唤醒一个阻塞任务。如果没有任务等待它,则释放一个资源(信号量加一)。

#include <semaphore.h>

       int sem_post(sem_t *sem);

参数:

        sem:信号量对象

 信号量+1
if(有等待资源的程序)
{
    将其唤醒;
}

 P、V操作测试代码如下:

包含线程的创建,结束线程和等待线程

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

void *get_data();
void *print_data();

char buf[64] = {0};

sem_t sem1;
sem_t sem2;

int main(int argc, char *argv[])
{
	pthread_t thread1,thread2;
	
	sem_init(&sem1, 0, 0);
	sem_init(&sem2, 0, 1);//信号量初始化	
		
	int ret = pthread_create(&thread1,NULL,get_data,NULL);//创建线程
	if(ret < 0)
	{
		perror("pthread_create");//创建失败,错误退出
		exit(-1);
	}
	ret = pthread_create(&thread2,NULL,print_data,NULL);
	if(ret < 0)
	{
		perror("pthread_create");
		exit(-1);
	}

	pthread_join(thread1, NULL);
	pthread_join(thread1, NULL);//等待线程
	return 0;
}

void *get_data()
{
	
	while(1)
	{
		sem_wait(&sem2);//申请资源
		fgets(buf, 64, stdin);//从键盘输入数据
		sem_post(&sem1);//释放资源
	}
}

void *print_data()
{
	while(1)
	{
		sem_wait(&sem1);
		printf("%s", buf);
		sem_post(&sem2);
		
	}
}

(2)互斥:当一个线程使用公共数据时,其他线程都不能访问该数据(互斥锁)

临界资源:多个线程能够共同访问的数据

临界区:涉及到临界资源的代码模块

互斥是使用互斥锁保护临界资源

4.互斥锁的相关操作接口函数:

(1) 创建互斥锁--互斥锁的初始化----pthread_mutex_init()

 #include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *mutex,pthread_mutexattr_t *attr);
参数:
    mutex:互斥锁对象(全局的)
    attr:互斥锁属性,填NULL使用缺省属性
返回值:
    成功返回0,失败返回-1

(2) 申请锁(上锁)---pthread_muutex_lock()  

 #include <pthread.h>
int pthread_muutex_lock( pthread_mutex_t *mutex);
参数:
    mutex:互斥锁对象

 (3)释放锁(打开)--pthread_mutex_unlock()

#include <pthread.h>
int pthread_mutex_unlock(pthread_mutex_t *mutex);
参数:
    mutex:互斥锁对象

 互斥锁测试,代码如下:

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

void *func();

int num1 = 0;
int num2 = 0;
int count = 0;

pthread_mutex_t mutex;

int main(int argc, char *argv[])
{
	pthread_t thread;
	
	int ret = pthread_mutex_init(&mutex, NULL);
	if(ret != 0)
	{
		perror("init failed!\n");
		exit(-1);
	}
	
	ret = pthread_create(&thread, NULL, func, NULL);
	if(ret < 0)
	{
		perror("pthread_create");
		exit(-1);
	}
	
	while(1)
	{
		pthread_mutex_lock(&mutex);
		num1 = count;
		num2 = count;
		count++;
		pthread_mutex_unlock(&mutex);
	}
	
	return 0;
}

void *func()
{
	while(1)
	{
		pthread_mutex_lock(&mutex);
		if(num1 != num2)
		{
			printf("num1 = %d  , num2 = %d\n",num1, num2);
		}
		pthread_mutex_unlock(&mutex);
	}
}

总结

                以上就是今天的内容,主要讲的是线程相关的接口函数以及线程间的通信,欢迎大家留评讨论!

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值