线程基础知识

目录

第1关:线程操作实战1

任务描述

相关知识

线程的退出等待

编程要求

答案:

第2关:线程操作实战2

任务描述

相关知识

取消线程

编程要求

答案:

第3关:线程操作实战3

任务描述

相关知识

线程全局变量与私有变量

编程要求

答案:


第1关:线程操作实战1

任务描述

本关任务:编写一个小程序取消已生成线程,然后输出入栈信息。

相关知识

为了完成本关任务,你需要掌握:线程栈的相关知识。

线程的退出等待

线程退出等待 1)pthread_exit(void* _retval) 库函数调用可以结束一个线程,结束方式和进程exit()类似。

2)等待线程 为了有效同步子线程,主线程中豆浆等待子线程结束,显示等待某线程结束可以调用pthread_join()函数,类似于进程的wait(),声明如下:

 int pthread_join(pthread_t _th, void **_pthread_return)
    _th 为被等待线程的ID(设置某个线程为独立线程,则可以调用pthread_detach(pthread_t __th))
    _pthread_return 为一个用户定义的指针,指向一个保存等待线程的完整退出状态的静态区域,用来存储被等待线程的返回值

阻塞调用当前线程的线程,直到此线程退出。当函数返回,处于被等待状态的线程资源被收回。

编程要求

根据提示,在右侧编辑器编写代码,增强对pthread_cleanup_push,pthread_cleanup_pop等函数的使用。

答案:
#include<pthread.h>
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>

void cleanup()
{
	printf("cleanup\n");
}
void *test_cancel(void)
{
	/*补充代码1,使用pthread_cleanup_push/pop,进行退出前操作*/
    pthread_cleanup_push(cleanup, NULL);
	printf("test_cancel\n");
	while(1)
	{
		printf("test message\n");
		sleep(1);
	}
	/*补充代码2,使用pthread_cleanup_push/pop,进行退出前操作*/
	 pthread_cleanup_pop(1);
}
int main()
{
	pthread_t tid;
	pthread_create(&tid,NULL,(void *)test_cancel,NULL);
	sleep(2);
	pthread_cancel(tid);
	pthread_join(tid,NULL);
}

第2关:线程操作实战2

任务描述

本关任务:编写一个小程序实现不同状态下的取消线程设置。

相关知识

为了完成本关任务,你需要掌握:取消线程的相关操作。

取消线程

(1)发起取消 即取消正在执行线程的操作,需要满足条件。 pthread_cancel()取消线程,调用的是取消线程清理处理程序(pthread_cleanup_push) 1)线程是否可以被取消,默认可以取消。 2)线程处于可取消点才能取消,发起取消不一定能立即取消,到取消点才可以。 (2)设置可取消状态 pthread_setcancelstate()和pthread_setcanceltype()用来设置和查询当前线程的可取消性状态或类型。

pthread_setcancelstate(int _state,int *_oldstate)
 state为要设置的新状态值;
 oldstate存储原来状态。
      1)PTHREAD_CANCEL_DISABLE 针对目标线程的取消请求将处于未决状态(未处理但存在)除非线程修改自己状态,否则不会被取消。
      2)PTHREAD_CANCEL_ENABLE,针对目标线程的取消请求将被传递,创建线程时是默认状态

(3)设置取消类型 pthread_setcanceltype()设置取消类型,在允许被取消的线程在接收到取消操作后是立即终止还是等到取消点终止。
 

int pthread_setcanceltype(int _type, int *_oldtype)
    type调用线程新的可取消性;
    oldtype存储原来的类型。
    PTHREAD_CANCEL_ASYNCHRONOUS,可随时执行新的或未决的取消请求。
    PTHREAD_CANCEL_DEFERRED,目标达到取消点前处于未决状态(请求已发出但未处理)

在创建线程时,可取消类型设置PTHREAD_CANCEL_DEFERRED,如果禁用线程的可取消性状态,则可取消性类型设置不会立即生效,取消请求都保留为未决状态。但一旦重新启用可取消性,新类型将会生效。 成功完成pthread_setcancelstate和pthread_setcanceltype将返回0,失败返回错误编号,不许设置error变量。

编程要求

根据提示,在右侧编辑器补充代码,代码思路是先开一个线程a_thread,调用thread_function函数,线程函数中先休眠1秒,然后输出一段提示,主函数休眠10秒,a_thread线程开始跑。function函数中,先将线程的可取消状态设置成DISABLE,当前无法取消线程,等待3秒输出当前线程无法取消,然后循环输出三次,每秒一次。将取消状态设置成ENABLE,可取消,线程休眠200秒,返回主程序,输出取消线程,主程序将线程取消pthread_cancel ,输出等待线程完成,pthread_join等待子线程结束,释放所有缓存。请补充代码,分别将取消状态设置为DISABLE和ENABLE。

答案:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>

void *thread_function(void *arg);

int main(int argc,char *argv[]) 
{
    int res;
    pthread_t a_thread;
    void *thread_result;

    res = pthread_create(&a_thread, NULL, thread_function, NULL);//创建线程
    if (res != 0) 
	{
        perror("Thread creation failed");
        exit(EXIT_FAILURE);
    }
    printf("Cancelling thread...\n");
    sleep(10);	
    res = pthread_cancel(a_thread);//取消子线程
    if (res != 0) 
	{
        perror("Thread cancelation failed");
        exit(EXIT_FAILURE);
    }
    printf("Waiting for thread to finish...\n");
    sleep(10);	
    res = pthread_join(a_thread, &thread_result);//等待子线程结束
    if (res != 0) 
	{
        perror("Thread join failed");
        exit(EXIT_FAILURE);
    }
    exit(EXIT_SUCCESS);
}

void *thread_function(void *arg) //新线程执行函数
{
    int i, res, j;
    sleep(1);
    /*请编写代码,将线程的取消状态设置为DISABLE*/
    res = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
    if (res != 0) 
	{
        perror("Thread pthread_setcancelstate failed");
        exit(EXIT_FAILURE);
    }
	sleep(3);
    printf("thread cancle type is disable,can't cancle this thread\n");//打印不可取消状态信息
    for(i = 0; i <3; i++) 
	{
        printf("Thread is running (%d)...\n", i);
        sleep(1);
    }

    /*请编写代码,将取消状态设置为ENABLE*/
    res = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);

    if (res != 0) 
	{
        perror("Thread pthread_setcancelstate failed");
        exit(EXIT_FAILURE);
    }
	else
		printf("Now change ths canclestate is ENABLE\n");
	sleep(7);//休眠7秒 
   pthread_exit(0);
}


第3关:线程操作实战3

 

任务描述

本关任务:编写一个小程序修改线程的私有变量查看对全局变量的影响。

相关知识

为了完成本关任务,你需要掌握并理解:线程的全局数据与私有数据。

线程全局变量与私有变量

经常用全局变量以实现多个函数共享数据,由于数据空间共享,全局变量共有,有的需要提供线程私有的全局变量,例如每个线程维护一个链表,使用相同函数操作,使用同名而不同内存地址的线程私有数据结构,这样的数据结构可以由POSIX线程库维护,称为线程私有数据TSD

(1)创建、注销线程私有数据

①创建TSD

pthread_key_create(pthread_ket_t *key,2)

从TSD池中分配一项,将其地址值赋给key,第二个参数不为空,在线程退出(pthread_exit())时以key所关联的数据为参数调用其指向的资源释放函数,以释放分配的缓冲区。 不论哪个线程调用pthread_key_create(),创建的key所有线程都可以访问,每个线程根据需要往key填入不同的值,提供了一个同名不同值的全局变量。

②注销TSD

int pthread_key_delete(pthread_key_t key)

这个函数不检查当前是否有线程正在使用TSD,也不会调用清理函数,只是将TSD释放供下一次调用pthread_key_create 使用。

(2)读写线程私有数据 TSD的读写通过专门的POSIX Thread函数进行

int pthread_setspecific(pthread_key_t key,const coid *pointer)
 void *pthread_getspecific(pthread_key_t key)

函数pthread_setspcific()将pointer的值(不是所指内容)与key相关联,pthread_getspecific()函数将与key相关联的数据读出。

,

,

先设置一个全局变量k=100,在主函数中先创建两个线程,线程1和2都输出线程赋值的字符串helloworld,线程2休眠1秒让线程1先跑,线程1将全局变量key改成10,输出key值和当前线程号,线程1跑完返回主线程pthread_join等待结束,线程2休眠完开跑,输出key,因为key值是全局变量,当前key已经被线程1修改,然后返回结束。

编程要求

根据提示,在右侧编辑器补充代码,代码思路是先创建两个线程child1、child2,两个线程同时开跑,线程1和2都输出当前欲修改的值以及自身的线程标识,然后分别用setspecific修改key值,为10和20,分别等待1秒和2秒,并打印当前的全局变量值,线程2先打印,线程1后打印,线程1和2分别都对私有的全局变量进行改变,但互不影响。请补充代码,分别将线程1的私有全局变量值修改成10,线程2 的私有全局变量值修改成20。

答案:
#include <stdio.h> 
#include <pthread.h> 

pthread_key_t key; //线程私有数据类型
void echomsg(void *t) 
{ 
	printf("destructor excuted\n"); //线程退出时执行
} 

void * child1(void *arg) 
{ 
	int i=10;
	int tid=pthread_self(); 
	printf("\nset key value %d in thread 1\n",i); 
	/*将线程1的私有key值修改为10*/
    pthread_setspecific(key, (void*)&i);

	printf("thread one sleep 2 until thread two finish\n");
	sleep(3); //等待线程2修改key值
	printf("\nthread 1 returns %d\n",*((int *)pthread_getspecific(key))); //打印当前线程信息
} 

void * child2(void *arg) 
{ 
	int temp=20;
	int tid=pthread_self(); 
	sleep(1); 
	printf("\nset key value %d in thread 2\n\n",temp); 
	/*将线程2的私有key值修改为20*/
    pthread_setspecific(key, (void*)&temp);

	sleep(1); 
	printf("thread 2 returns %d\n",*((int *)pthread_getspecific(key))); //打印当前线程信息
} 

int main(void) 
{ 
	pthread_t tid1,tid2; 
	pthread_key_create(&key,echomsg); 
	pthread_create(&tid1,NULL,(void *)child1,NULL); //创建线程1
	pthread_create(&tid2,NULL,(void *)child2,NULL); //创建线程2
	pthread_join(tid1,NULL);//等待线程1结束
	pthread_join(tid2,NULL);//等待线程2结束
	pthread_key_delete(key); //释放全局变量
	return 0; 
} 
  • 18
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
### 回答1: 多线程实战PDF是一本介绍多线程编程实践的PDF电子书。多线程是指在一个程序中同时运行多个线程,每个线程都可以执行不同的任务。多线程可以提高程序的执行效率、响应速度和资源利用率,是现代计算机应用中常用的技术。 该电子书主要介绍了多线程编程的原理、方法和实践经验。首先,它从多线程的基本概念和原理入手,介绍了线程的创建、启动、终止和同步等基本操作。然后,它详细介绍了多线程编程中常见的问题和解决方案,如线程间的通信、资源竞争、死锁和并发性问题等。同时,它还介绍了多线程编程的一些高级技术,如线程池、信号量、互斥锁和条件变量等。 该电子书还通过实例代码和案例分析,给读者提供了一些实战经验。例如,它介绍了如何利用多线程实现文件下载、图像处理、网络爬虫和并行计算等常见应用场景。同时,它还介绍了如何利用多线程优化程序性能,如通过并行计算加速算法的运行、利用线程池提高任务处理能力等。 总之,多线程实战PDF是一本介绍多线程编程实践的电子书,它详细介绍了多线程编程的原理、方法和实践经验,并通过实例代码和案例分析给读者提供了一些实战经验。对于想要学习和应用多线程编程的人来说,这本电子书是一个很好的参考资料。 ### 回答2: 多线程是一种可以同时执行多个任务的编程技术,它可以提高程序的运行效率和响应速度。在实际应用中,我们可以利用多线程来处理一些需要同时执行的任务,例如同时下载多个文件、同时进行图像处理等。 在实现多线程的应用中,我们通常会遇到一些问题,如线程之间的数据共享、线程的同步与互斥等。为了更好地理解多线程的使用和解决这些问题,可以通过实践来加深理解。 以一个线程实战的PDF为例,假设我们需要编写一个程序,能够同时下载多个PDF文件并保存到本地。我们可以首先定义一个下载函数,在该函数中使用多线程来实现同时下载多个PDF文件的功能。 在下载函数中,我们可以通过创建多个线程,并将每个线程分配到不同的下载任务上。通过在每个线程中实现下载逻辑,我们可以同时进行多个文件的下载,提高下载效率。 同时,为了确保线程之间的数据共享和操作的正确性,我们可以使用一些同步机制,如互斥锁(mutex)和条件变量(condition),来保证线程之间的协作和安全性。通过这些同步机制,我们可以避免多个线程同时访问和修改共享资源的问题,保证下载的正确进行。 在实际编写的过程中,我们还可以优化多线程的性能,例如合理设置线程的数量、调整下载任务的分配策略等。同时,我们也需要考虑一些问题,如线程的优雅退出、线程的异常处理等,以确保程序的健壮性。 总之,多线程实战PDF是一个相当实用和有意义的应用场景,通过实践和理论相结合的方式,我们可以更好地理解和掌握多线程的使用,提高程序的效率和可靠性。 ### 回答3: C多线程实战PDF是一本介绍多线程编程并提供实际案例的电子书籍。多线程是指在一个程序中同时执行多个线程,可以充分利用计算机资源,提高程序的运行效率。本书通过具体的项目实例,重点讲解了如何在C语言中实现多线程编程。 本书首先介绍了多线程的概念和原理,包括线程的创建、同步与互斥、线程的调度等基本知识。然后通过实战项目,让读者学会如何使用多线程解决实际问题。这些实战案例涵盖了多个领域,如网络编程、图像处理、并行计算等,旨在帮助读者理解多线程的应用场景和技巧。 在实战案例中,读者将学习如何使用多线程编写一个简单的Web服务器,实现同时处理多个HTTP请求。同时,还可以学习如何使用多线程进行图像处理,例如并行地对图像进行压缩或特效处理。此外,本书还介绍了如何使用多线程进行并行计算,以提高程序的性能。 C多线程实战PDF适合有一定C语言编程基础的读者学习。通过阅读本书,读者可以深入了解多线程编程的原理和技术,掌握多线程编程的核心概念和方法,并能灵活应用于实际项目中。无论是对于想要提升编程技能的程序员,还是对于对多线程编程感兴趣的技术爱好者,本书都是一本很好的学习资料。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星与星熙.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值