实验七:Linux多线程编程(实验分析报告)

合集下载

线程实验报告

线程实验报告

线程实验报告线程实验报告引言:线程是计算机科学中的一个重要概念,它是操作系统能够进行运算调度的最小单位。

线程的使用能够提高程序的并发性和响应性,使得程序能够更高效地利用计算机资源。

本次实验旨在通过编写一个简单的多线程程序,来探究线程的工作原理和应用。

实验目的:1. 了解线程的基本概念和特点;2. 掌握线程的创建、同步和销毁方法;3. 理解多线程编程的优势和挑战。

实验过程:1. 创建线程在实验开始时,我们首先需要创建线程。

在C++中,可以使用pthread库来实现。

通过调用pthread_create函数,我们可以创建一个新的线程,并将其与指定的函数进行绑定。

在实验中,我们创建了两个线程,分别执行不同的任务。

2. 线程同步在多线程编程中,线程之间的同步是一个重要的问题。

为了避免竞态条件和资源争用,我们需要使用互斥锁和条件变量等同步机制。

在本次实验中,我们使用了互斥锁来保护共享资源的访问,以及条件变量来实现线程之间的通信。

3. 线程销毁线程的销毁是一个关键的步骤。

在实验中,我们使用了pthread_join函数来等待线程的结束,并回收线程的资源。

这样可以确保线程的正确退出,避免资源泄漏和程序崩溃。

实验结果:通过实验,我们发现多线程编程具有以下优势:1. 提高程序的并发性:通过并行执行多个任务,可以提高程序的运行效率,减少等待时间。

2. 增强程序的响应性:多线程可以使程序具有更好的交互性,用户可以在任务执行的同时进行其他操作。

3. 充分利用计算机资源:多线程能够充分利用多核处理器的计算能力,提高系统的整体性能。

然而,多线程编程也存在一些挑战:1. 竞态条件:当多个线程同时访问共享资源时,可能会导致数据的不一致性和程序的错误。

2. 死锁和饥饿:线程之间的同步问题可能导致死锁和饥饿现象,使得程序无法正常执行。

3. 调试困难:多线程程序的调试比单线程程序更加困难,需要仔细分析线程之间的交互关系。

结论:通过本次实验,我们深入了解了线程的工作原理和应用。

操作系统实验报告理解Linux下进程和线程的创建并发执行过程。

操作系统实验报告理解Linux下进程和线程的创建并发执行过程。

操作系统上机实验报告实验名称:进程和线程实验目的:理解unix/Linux下进程和线程的创建、并发执行过程。

实验内容:1.进程的创建2.多线程应用实验步骤及分析:一、进程的创建下面这个C程序展示了UNIX系统中父进程创建子进程及各自分开活动的情况。

fork( )创建一个新进程。

系统调用格式:pid=fork( )参数定义:int fork( )fork( )返回值意义如下:0:在子进程中,pid变量保存的fork( )返回值为0,表示当前进程是子进程。

>0:在父进程中,pid变量保存的fork( )返回值为子进程的id值(进程唯一标识符)。

-1:创建失败。

如果fork( )调用成功,它向父进程返回子进程的PID,并向子进程返回0,即fork( )被调用了一次,但返回了两次。

此时OS在内存中建立一个新进程,所建的新进程是调用fork( )父进程(parent process)的副本,称为子进程(child process)。

子进程继承了父进程的许多特性,并具有与父进程完全相同的用户级上下文。

父进程与子进程并发执行。

2、参考程序代码/*process.c*/#include <stdio.h>#include <sys/types.h>main(int argc,char *argv[]){int pid;/* fork another process */pid = fork();if (pid < 0) { /* error occurred */fprintf(stderr, "Fork Failed");exit(-1);}else if (pid == 0) { /* child process */execlp( "/bin/ls", "ls",NULL);}else {/* parent process *//* parent will wait for the child to complete */ wait(NULL);printf( "Child Complete" );exit(0);}}3、编译和运行$gcc process.c –o processs4、运行$./process编辑如图所示:运行如图所示:思考:(1)系统是怎样创建进程的?1,申请空白PCB(进程控制块);2,为新进程分派资源;3,初始化PCB;4,将新进程插入就绪队列;(2)扩展程序,在父进程中输出1到5,在子进程中输出6-10,要求父子进程并发输出;记录实验结果,并给出简单分析。

多线程程序实验报告(3篇)

多线程程序实验报告(3篇)

第1篇一、实验目的1. 理解多线程的概念和作用。

2. 掌握多线程的创建、同步和通信方法。

3. 熟悉Java中多线程的实现方式。

4. 提高程序设计能力和实际应用能力。

二、实验环境1. 操作系统:Windows 102. 开发工具:IntelliJ IDEA3. 编程语言:Java三、实验内容本次实验主要完成以下任务:1. 创建多线程程序,实现两个线程分别执行不同的任务。

2. 使用同步方法实现线程间的同步。

3. 使用线程通信机制实现线程间的协作。

四、实验步骤1. 创建两个线程类,分别为Thread1和Thread2。

```javapublic class Thread1 extends Thread {@Overridepublic void run() {// 执行Thread1的任务for (int i = 0; i < 10; i++) {System.out.println("Thread1: " + i);}}}public class Thread2 extends Thread {@Overridepublic void run() {// 执行Thread2的任务for (int i = 0; i < 10; i++) {System.out.println("Thread2: " + i);}}}```2. 创建一个主类,在主类中创建两个线程对象,并启动它们。

```javapublic class Main {public static void main(String[] args) {Thread thread1 = new Thread1();Thread thread2 = new Thread2();thread1.start();thread2.start();}```3. 使用同步方法实现线程间的同步。

```javapublic class SynchronizedThread extends Thread {private static int count = 0;@Overridepublic void run() {for (int i = 0; i < 10; i++) {synchronized (SynchronizedThread.class) {count++;System.out.println(Thread.currentThread().getName() + ": " + count);}}}}public class Main {public static void main(String[] args) {Thread thread1 = new SynchronizedThread();Thread thread2 = new SynchronizedThread();thread1.start();thread2.start();}```4. 使用线程通信机制实现线程间的协作。

实验7_多线程编程

实验7_多线程编程

实验7--多线程编程7.1 实验目的(1) 掌握多线程编程的特点;(2) 了解线程的调度和执行过程;(3)掌握资源共享访问的实现方法。

7.2 知识要点7.2.1线程的概念(1)线程是程序中的一个执行流,多线程则指多个执行流;(2)线程是比进程更小的执行单位,一个进程包括多个线程;(3)Java语言中线程包括3部分:虚拟CPU、该CPU执行的代码及代码所操作的数据。

(4)Java代码可以为不同线程共享,数据也可以为不同线程共享;7.2.2 线程的创建(1) 方式1:实现Runnable接口Thread类使用一个实现Runnable接口的实例对象作为其构造方法的参数,该对象提供了run方法,启动Thread将执行该run方法;(2)方式2:继承Thread类重写Thread类的run方法;7.2.3 线程的调度(1) 线程的优先级●取值范围1~10,在Thread类提供了3个常量,MIN_PRIORITY=1、MAX_PRIORITY=10、NORM_PRIORITY=5;●用setPriority()设置线程优先级,用getPriority()获取线程优先级;●子线程继承父线程的优先级,主线程具有正常优先级。

(2) 线程的调度:采用抢占式调度策略,高优先级的线程优先执行,在Java中,系统按照优先级的级别设置不同的等待队列。

7.2.4 线程的状态与生命周期说明:新创建的线程处于“新建状态”,必须通过执行start()方法,让其进入到“就绪状态”,处于就绪状态的线程才有机会得到调度执行。

线程在运行时也可能因资源等待或主动睡眠而放弃运行,进入“阻塞状态”,线程执行完毕,或主动执行stop方法将进入“终止状态”。

7.2.5 线程的同步--解决资源访问冲突问题(1) 对象的加锁所有被共享访问的数据及访问代码必须作为临界区,用synchronized加锁。

对象的同步代码的执行过程如图14-2所示。

synchronized关键字的使用方法有两种:●用在对象前面限制一段代码的执行,表示执行该段代码必须取得对象锁。

北京科技大学嵌入式系统实验6---嵌入式Linux 多线程编程实验

北京科技大学嵌入式系统实验6---嵌入式Linux 多线程编程实验

北京科技大学实验报告学院:自动化学院专业:班级:姓名:学号:实验日期:2018年5月7日实验名称:实验六嵌入式Linux多线程编程实验实验目的:1.掌握线程的运行机制、创建方法及特点。

2.掌握线程退出、线程等待、线程清除等函数的使用方法。

3.学会线程的数据处理方法。

实验仪器:linux操作系统64位实验内容与步骤:编写程序,完成如下五个功能,要求写出编程思路、实验步骤,显示程序运行结果,并进行必要的分析。

1)有一个int型全局变量g_Flag初始值为0;2)在主线程中起动线程1,打印“this is thread1”,并将g_Flag设置为1;3)在主线程中启动线程2,打印“this is thread2”,并将g_Flag设置为2;4)线程1需要在线程2退出后才能退出;5)主线程在检测到g_Flag从1变为2,或者从2变为1的时候退出。

实验数据:编程思路:本实验我是主要是用到进程与线程相关的概念,有关线程操作的函数,线程之间的互斥以及线程之间的同步这些内容,在编写程序代码时,首先定义一个int型全局标志g_Flag,设置其初始值大小为0,初始化进程锁pthread_mutex_t mutex,然后初始化条件变量pthread_cond_t cond,声明两个线程函数,分别为thread1和thread2,定义两个线程id分别为tid1和tid2,创建线程,如果线程创建成功的话就返回0,否则的话就返回一个正数,如果rc2不等于0的话,说明创建错误,在线程1程序入口,启动进程thread1,输出enter thread,执行进程1打印出this is thread1,g_Flag的值也同时输出,输出结果为1,得到当前线程id,接下来如启动进程互斥锁,如果g_Flag的值为2则说明线程thread2已经执行了,这时候进程2打印出this is thread2,g_Flag的值为2,首先退出进程2,然后再退出进程1,通过调用pthread_exit()函数实现进程的退出,当g_Flag的值发生变化,当其从1变为2或者从2变为1时,主线程能够检测到g_Flag发生的变化,调用pthread_exit()函数退出主线程。

Linux实验总结分析报告

Linux实验总结分析报告

Linux实验总结分析报告精简的 Linux 系统模型从整体⽽⾔,Linux系统分为⽤户空间和内核空间两部分,按照功能可以划分为进程管理、内存管理、⽂件管理以及设备管理,这些有关计算机底层的操作都只能在内核空间进⾏。

完整的Linux内核运⾏于内核空间,它管理底层的所有硬件设备;⽤户空间可以通过系统调⽤接⼝来使⽤特权操作,存在⼀个⽤户态向内核态的切换过程;Linux 内核Linux内核运⾏在内核空间,向下负责管理计算机系统的硬件设备,向上为应⽤程序提供服务⽀持。

主要提供以下服务:系统调⽤接⼝、中断管理、进程管理、内存管理、⽂件系统以及硬件驱动程序。

进程管理进程是处于执⾏期的程序以及相关资源的总称。

线程在linux上称为轻量级进程,没有独⽴的地址空间,⼀个进程下的所有线程共享地址空间、⽂件系统资源、⽂件描述符、信号处理程序等。

进程管理是⼀个操作系统内核的核⼼实现部分,进程的调度管理等⼀系列操作都由此完成;1. 什么是进程?在Linux内核中,⼀个进程使⽤⼀个PCB(task_struct)来描述⼀个进程,进程是⼀个程序的执⾏过程,是程序的动态体现。

2. 进程的状态:有五个,创建 / 就绪 / 阻塞 / 运⾏ / 结束,其中最主要的状态有三个:就绪 / 阻塞 / 运⾏。

3. 进程的切换:通过切换进程的虚拟地址空间和CPU的执⾏上下⽂实现。

即:切换⻚全局⽬录(CR3)以安装⼀个新的地址空间和切换内核态堆栈和进程的CPU上下⽂,因为进程的CPU上下⽂提供了内核执⾏新进程所需要的所有信息,包含所有CPU寄存器状态。

4. 调度时机:有三种1. 内核线程主动调⽤schedule函数2. ⽤户进程上下⽂中主动调⽤系统调⽤,进⼊中断上下⽂,在系统调⽤返回⽤户态前进⾏进程调度3. 内核进程或可中断的中断处理程序,执⾏过程中发⽣中断进⼊中断上下⽂,在中断返回前进⾏进程调度内存管理内存是计算机系统中主要的资源,在Linux中,内存空间被分为⽤户空间和内核空间两⼤块。

linux进程线程管理实验报告

linux进程线程管理实验报告————————————————————————————————作者:————————————————————————————————日期:西安郵電學院操作系统LINUX实验报告题目1:进程______题目2:线程管理__题目3:互斥_____系部名称:计算机学院专业名称:软件工程班级:0802学号:04085048学生姓名:郭爽乐时间:2010-10-31实验一: 进程管理一.实验目的通过观察、分析实验现象,深入理解进程及进程在调度执行和内存空间等方面的特点,掌握在POSIX 规范中fork和kill系统调用的功能和使用。

二.实验要求2.1 实验环境要求1. 硬件(1) 主机:Pentium III 以上;(2) 内存:128MB 以上;(3) 显示器:VGA 或更高;(4) 硬盘空间:至少100MB 以上剩余空间。

2. 软件Linux 操作系统,内核2.4.26 以上,预装有X-Window 、vi、gcc、gdb 和任意web 浏览器。

2.2 实验前的准备工作学习man 命令的用法,通过它查看fork 和kill 系统调用的在线帮助,并阅读参考资料,学会fork 与kill 的用法。

复习C 语言的相关内容。

三、实验内容3.1 补充POSIX 下进程控制的残缺版实验程序3.2回答下列问题:1. 你最初认为运行结果会怎么样?2. 实际的结果什么样?有什么特点?试对产生该现象的原因进行分析。

3. proc_number 这个全局变量在各个子进程里的值相同吗?为什么?4. kill 命令在程序中使用了几次?每次的作用是什么?执行后的现象是什么?5. 使用kill 命令可以在进程的外部杀死进程。

进程怎样能主动退出?这两种退出方式哪种更好一些?四、实验结果4.1 补充完全的源程序#include<stdio.h>#include<sys/types.h>#include<unistd.h>#include<signal.h>#include<ctype.h>#define MAX_CHILD_NUMBER 10/* 允许建立的子进程个数最大值 */ #define SLEEP_INTERV AL 1/* 子进程睡眠时间 */int proc_number=0; /* 子进程的编号,从0开始 */void do_something();main(int argc,char *argv[]){int child_proc_number=MAX_CHILD_NUMBER; /* 子进程个数 */ int i,ch;pid_t child_pid;pid_t pid[10]={0};/* 存放每个子进程的id */if(argc>1){child_proc_number=atoi(argv[1]);child_proc_number=(child_proc_number>10)?10:child_proc_number; /* 命令行参数中的第一个参数表示建立几个子进程,最多10个 */ }/*建立child_proc_number个子进程* 子进程要执行* proc_number = i;* do_something();* 父进程把子进程的id保存到pid[i] */for(i=0;i<child_proc_number;i++){child_pid=fork();if(child_pid== -1){perror("creat error!\n");return 1;}else if(child_pid>0)pid[i]=child_pid;else{proc_number=i;do_something();}}/* 让用户选择杀死哪个进程。

Linux实验总结分析报告

Linux实验总结分析报告⼀、Linux系统概念模型从整体来看,Linux可以划分为⽤户空间和内核空间,我们平常编写的⽤户程序以及C库函数都位于⽤户空间,⽽内核空间⾃顶向下可分为系统调⽤、内核(进程管理、内存管理、⽂件管理、中断等)以及平台架构相关代码。

1、Linux启动分析当我们打开PC的电源,BIOS开机⾃检,按BIOS中设置的启动设备(通常是硬盘)启动,接着启动设备上安装的引导程序lilo或grub开始引导Linux,Linux⾸先进⾏内核的引导,接下来执⾏init程序,init程序调⽤了rc.sysinit和rc等程序,rc.sysinit和rc当完成系统初始化和运⾏服务的任务后,返回init;init启动了mingetty后,打开了终端供⽤户登录系统,⽤户登录成功后进⼊了Shell,这样就完成了从开机到登录的整个启动过程。

2、进程管理linux内核通过task_struct(进程描述符)结构体来管理进程,多个任务的task struct组成的链表,被称为task list(任务列表)。

(1)进程创建:在Linux系统中,所有的进程都是PID为1的init进程的后代。

内核在系统启动的最后阶段启动init进程。

该进程读取系统的初始化脚本(initscript)并执⾏其他的相关程序,最终完成系统启动的整个进程。

Linux提供两个函数去处理进程的创建和执⾏:fork()和exec()。

⾸先,fork()通过拷贝当前进程创建⼀个⼦进程。

⼦进程与⽗进程的区别仅仅在于PID(每个进程唯⼀),PPID(⽗进程的PID)和某些资源和统计量(例如挂起的信号)。

exec()函数负责读取可执⾏⽂件并将其载⼊地址空间开始运⾏。

(2)进程终⽌依靠do_exit()(在kernel/exit.c⽂件中)把与进程相关联的所有资源都被释放掉(假设进程是这些资源的唯⼀使⽤者)。

⾄此,与进程相关的所有资源都被释放掉了。

进程不可运⾏(实际上也没有地址空间让它运⾏)并处于TASK_ZOMBIE状态。

系统平台实验7-线程同步与多线程编程

实验7 线程同步与多线程编程一、实验目的通过本实验了解和掌握线程的相关知识,使学生(1)了解系统中线程同步的基本原理。

(2)了解和熟悉多线程编程及线程访问控制。

二、实验内容1. 生产者-消费者问题用信号量实现生产者-消费者问题。

分析:信号量的考虑这里使用3个信号量,其中两个信号量empty和full分别用于解决生产者和消费者线程之间的同步问题,mutex是用于这两个线程之间的互斥问题。

其中empty初始化为N(缓冲区的单元数),mutex初始化为1,full初始化为0。

程序流程如下:1)开始->建立有名管道->打开有名管道->初始化3个信号量->创建消费者和生产者两个线程。

2)生产者线程。

wait操作(empty)->wait操作(mutex)->写管道->signal操作(full)->signal 操作(mutex)。

3)消费者线程。

请自己实现。

源代码:exp71.c#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <pthread.h>#include <errno.h>#include <sys/ipc.h>#include <semaphore.h>#include <fcntl.h>#include <time.h>#include <string.h>#define FIFO "myfifo"#define N 5int lock_var;time_t end_time;char buf_r[100];定义buf_r数组表示缓冲区sem_t mutex,full,empty;互斥信号量木特性,信号量empty表示缓冲池中空幻吃区适量,full 表示满缓冲区适量int fd;void producer(void *arg);void consumer(void *arg);int main(int argc,char *argv[]){pthread_t id1,id2;pthread_t mon_th_id;int ret;end_time=time(NULL)+10;创建管道if((mkfifo(FIFO,0777|O_CREAT)<0)&&(errno!=EEXIST))printf("cannot creat fifoserver\n");printf("Preparing for reading bytes\n");memset(buf_r,0,sizeof(buf_r));打开管道fd=open(FIFO,O_RDWR|O_NONBLOCK,0);if(fd==-1){perror("open");exit(1);}初始化互斥信号和empty full缓冲区ret=sem_init(&mutex,0,1);ret=sem_init(&empty,0,N);ret=sem_init(&full,0,0);if(ret!=0){perror("sem_init");}ret=pthread_create(&id1,NULL,(void*)producer,NULL);创建生产者线程创建成功返回0 if(ret!=0)perror("pthread create1");ret=pthread_create(&id2,NULL,(void*)consumer,NULL);创建消费者线程创建成功返回0.if(ret!=0)perror("pthread create2");pthread_join(id1,NULL);等待生产者线程结束pthread_join(id2,NULL);等待消费者县城结束exit(0);}void producer(void *arg){int i,nwrite;while(time(NULL)<end_time){sem_wait(&empty);空缓冲区的信号量减一sem_wait(&mutex);互斥信号量减一变为0。

linux程序设计实验报告

linux程序设计实验报告Linux程序设计实验报告引言在计算机科学领域,操作系统是一项至关重要的基础设施。

Linux作为一种开源的操作系统,具有广泛的应用和开发者社区。

本次实验旨在通过Linux程序设计,深入了解Linux操作系统的内部机制和编程技巧。

一、实验背景与目的Linux操作系统以其稳定性、安全性和灵活性而闻名。

本次实验的目的是通过编写Linux程序,探索Linux操作系统的核心原理和实践技巧。

通过实践操作,我们可以更好地理解Linux内核、进程管理、文件系统和网络通信等方面的工作原理。

二、实验环境与工具本次实验使用的实验环境为Ubuntu操作系统,我们将使用C语言进行程序设计。

以下是本次实验所用到的工具和软件:1. Ubuntu 18.04 LTS操作系统2. GCC编译器3. GNU Make工具4. Vim文本编辑器三、实验内容与步骤1. 进程管理在Linux操作系统中,进程是程序的执行实例。

我们将通过编写一个简单的多进程程序来理解进程的创建、调度和终止。

首先,我们需要使用fork()系统调用创建一个新的子进程。

然后,通过exec()系统调用加载一个新的程序到子进程中。

最后,使用wait()系统调用等待子进程的结束并回收资源。

2. 文件系统Linux操作系统中的文件系统是一种层次化的存储结构。

我们将通过编写一个简单的文件读写程序来理解文件系统的基本操作。

首先,我们需要使用open()系统调用打开一个文件,并指定读写权限。

然后,使用read()和write()系统调用读取和写入文件的内容。

最后,使用close()系统调用关闭文件。

3. 网络通信Linux操作系统提供了丰富的网络通信功能。

我们将通过编写一个简单的网络通信程序来理解网络套接字的使用。

首先,我们需要使用socket()系统调用创建一个套接字,并指定通信协议。

然后,使用bind()系统调用将套接字绑定到指定的IP地址和端口号。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验七:Linux多线程编程(实验报告)

2

———————————————————————————————— 作者: ———————————————————————————————— 日期:

3

实验七:Linux多线程编程(4课时) 实验目的:掌握线程的概念;熟悉Linux下线程程序编译的过程;掌握多线程程序编写方法。 实验原理:为什么有了进程的概念后,还要再引入线程呢?使用多线程到底有哪些好处?什么的系统应该选用多线程?我们首先必须回答这些问题。 1 多线程概念 使用多线程的理由之一是和进程相比,它是一种非常"节俭"的多任务操作方式。运行于一个进程中的多个线程,它们彼此之间使用相同的地址空间,共享大部分数据,启动一个线程所花费的空间远远小于启动一个进程所花费的空间。 使用多线程的理由之二是线程间方便的通信机制。同一进程下的线程之间共享数据空间,所以一个线程的数据可以直接为其它线程所用,这不仅快捷,而且方便。 2多线程编程函数 Linux系统下的多线程遵循POSIX线程接口,称为pthread。编写Linux下的

多线程程序,需要使用头文件pthread.h,连接时需要使用库libpthread.a。 pthread_t在头文件/usr/include/bits/pthreadtypes.h中定义: typedef unsigned long int pthread_t; 它是一个线程的标识符。 函数pthread_create用来创建一个线程,它的原型为: extern int pthread_create((pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg)); 第一个参数为指向线程标识符的指针,第二个参数用来设置线程属性,第三个参数是线程运行函数的起始地址,最后一个参数是运行函数的参数。 函数pthread_join用来等待一个线程的结束。函数原型为: extern int pthread_join(pthread_t th, void **thread_return); 第一个参数为被等待的线程标识符,第二个参数为一个用户定义的指针,它可以用来存储被等待线程的返回值。 函数pthread_exit的函数原型为: extern void pthread_exit(void *retval); 唯一的参数是函数的返回代码,只要pthread_join中的第二个参数thread_return不是NULL,这个值将被传递给 thread_return。

3 修改线程的属性 线程属性结构为pthread_attr_t,它在头文件/usr/include/pthread.h中定义。属性值不能直接设置,须使用相关函数进行操作,初始化的函数为pthread_attr_init,这个函数必须在pthread_create函数之前调用。

设置线程绑定状态的函数为 pthread_attr_setscope,它有两个参数,第一个是指向属性结构的指针,第二个是绑定类型,它有两个取值:PTHREAD_SCOPE_SYSTEM(绑定的)和PTHREAD_SCOPE_PROCESS(非

绑定的)。 另外一个可能常用的属性是线程的优先级,它存放在结构sched_param中。用函数pthread_attr_getschedparam和函数 pthread_attr_setschedparam进行存放,一般说来,我们总是先取优先级,

对取得的值修改后再存放回去。 4 线程的数据处理

4

和进程相比,线程的最大优点之一是数据的共享性,各个进程共享父进程处沿袭的数据段,可以方便的获得、修改数据。但这也给多线程编程带来了许多问题。我们必须当心有多个不同的进程访问相同的变量。许多函数是不可重入的,即同时不能运行一个函数的多个拷贝(除非使用不同的数据段)。在函数中声明的静态变量常常带来问题,函数的返回值也会有问题。 互斥锁 互斥锁用来保证一段时间内只有一个线程在执行一段代码。必要性显而易见:假设各个线程向同一个文件顺序写入数据,最后得到的结果一定是灾难性的。 条件变量 互斥锁一个明显的缺点是它只有两种状态:锁定和非锁定。而条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用。使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化。 信号量 信号量既可以作为二值计数器(即0,1),也可以作为资源计数器. 信号量本质上是一个非负的整数计数器,它被用来控制对公共资源的访问。当公共资源增加时,调用函数sem_post()增加信号量。只有当信号量值大于0时,才能使用公共资源,使用后,函数sem_wait()减少信号量。函数sem_trywait()和函数pthread_ mutex_trylock()起同样的作用,它是

函数sem_wait()的非阻塞版本。

实验内容:线程函数编译时需要添加特殊编译选项:gcc *.c -lpthread -o 1、 完成教材上thread.c的例子,想一下每次执行时结果相同吗,为什么?

答:每个线程的运行和结束时无序的、独立与并行的。 实验代码: /* thread.c */ #include #include #include #define THREAD_NUMBER 3 /*线程数*/ #define REPEAT_NUMBER 5 /*每个线程中的小任务数*/ #define DELAY_TIME_LEVELS 6.0 /*小任务之间的最大时间间隔*/ void *thrd_func(void *arg) //指针好乱,这里看不懂定义了什么,求解释 //定义了一个返回值为指向空类型的指针的函数,该函数的参数为一个指针 { /* 线程函数例程 */ int thrd_num = (int)arg; //这个是赋值吗?看不懂,求解释 //定义了一个整型参数,取值为arg int delay_time = 0; int count = 0; printf("Thread %d is starting\n", thrd_num); for (count = 0; count < REPEAT_NUMBER; count++) { delay_time = (int)(rand() * DELAY_TIME_LEVELS/(RAND_MAX)) + 1;

5

printf("\tThread %d: job %d delay = %d\n",thrd_num, count, delay_time); sleep(delay_time); //暂停?秒 //暂停随机秒 } //\t 输出一个Tab 占8列 //输出格式 : Thread thrd_num: job count delay = delay_time 回车 printf("Thread %d finished\n", thrd_num); //输出格式: Thread thrd_num finished 回车 pthread_exit(NULL); } int main(void) { pthread_t thread[THREAD_NUMBER]; //定义了一个类型为pthread_t的数组,数组元素的个数为3 int no = 0, res; void * thrd_ret; //这句什么意思?求解释 //定义了一个指针,指向哪里后面的程序里有。 srand(time(NULL)); //这句什么意思? 求解释 //用系统时间计算一个随机数。 for (no = 0; no < THREAD_NUMBER; no++) { /* 创建多线程 */ res = pthread_create(&thread[no], NULL, thrd_func, (void*)no); //&thread[no]线程标识符 //pthread_create函数的参数含义请看书。 if (res != 0) //创建线程出错时 res=错误码 { printf("Create thread %d failed\n", no); exit(res);//上面的不是退出进程,而是判断pthread_create()函数是否成功执行。 } } printf("Create treads success\n Waiting for threads to finish...\n"); //如果上面没退出进程,则创建线程成功 for (no = 0; no < THREAD_NUMBER; no++) { /* 等待线程结束 */ res = pthread_join(thread[no], &thrd_ret); // thread[no]线程标识符,此例总共有thread[0],thread[1],thread[2],3个线程 //请看书上pthread_join()函数的参数含义。 if (!res) //res=0时,挂起线程成功 //res=0时,说明pthread_join()函数执行成功。 { printf("Thread %d joined\n", no); } else {

相关文档
最新文档