文档库 最新最全的文档下载
当前位置:文档库 › 线程的三个实验

线程的三个实验

线程的三个实验
线程的三个实验

线程的三个实验

实验要求:(1)创建两个线程,每个线程的工作是在自己界面的TextField区域中从左到右动态地显示一个字符串,可通过界面按钮启动和中止每个线程的运行。

//閬楃暀闂 锛氱嚎绋嬪悓鏃剁潯鐪狅紵锛燂紵锛熺紦瀛樹竴涓嬪瓙杈撳嚭锛燂紵锛?import java.awt.*;

import java.awt.Color;

import java.awt.Container;

import java.awt.FlowLayout;

import java.awt.GridLayout;

import javax.swing.*;

import java.awt.event.*;

public class ThreadTester1 extends JFrame

{

private JButton runButton1,runButton2;

private JButton interruptButton1,interruptButton2;

private JTextArea threadTextArea1,threadTextArea2;

private JTextField sleepTextField1,sleepTextField2;

private ThreadTest threadtest1,threadtest2;

private Container container;

public ThreadTester1()

{

container=this.getContentPane();

setnew();

layoutSet();

String string1="hello!my name is jj",string2="how are you?my name is zwc";

threadtest1=new ThreadTest(threadTextArea1,string1,"thread1");

threadtest2=new ThreadTest(threadTextArea2,string2,"thread2");

setSize(400,200);

setVisible(true);

}

private void setnew()

{

ButtonHandler buttonhandler=new ButtonHandler();

runButton1=new JButton("鍚 姩");

runButton1.addActionListener(buttonhandler);

runButton2=new JButton("鍚 姩");

runButton2.addActionListener(buttonhandler);

interruptButton1=new JButton("涓 柇");

interruptButton1.addActionListener(buttonhandler);

interruptButton2=new JButton("涓 柇");

interruptButton2.addActionListener(buttonhandler);

threadTextArea1=new JTextArea();

threadTextArea1.setBackground(Color.CY AN);

threadTextArea2=new JTextArea();

threadTextArea2.setBackground(Color.CY AN);

sleepTextField1=new JTextField(8);

sleepTextField1.addActionListener(new TextFieldHandler1());

sleepTextField2=new JTextField(8);

sleepTextField2.addActionListener(new TextFieldHandler2()); }

private void layoutSet()

{

this.setLayout(new GridLayout(4,1));

JPanel panel1=new JPanel(new FlowLayout());

panel1.setBackground(Color.GREEN);

panel1.add(new JLabel("鐫$湢鏃堕棿锛?));

panel1.add(this.sleepTextField1);

panel1.add(this.runButton1);

panel1.add(this.interruptButton1);

JPanel panel2=new JPanel(new FlowLayout());

panel2.setBackground(Color.GREEN);

panel2.add(new JLabel("鐫$湢鏃堕棿锛?));

panel2.add(this.sleepTextField2);

panel2.add(this.runButton2);

panel2.add(this.interruptButton2);

container.add(this.threadTextArea1);

container.add(panel1);

container.add(this.threadTextArea2);

container.add(panel2);

}

private class ButtonHandler implements ActionListener

{

public void actionPerformed(ActionEvent event)

{

if(event.getSource()==runButton1)

{

try

{

if(threadtest1.isAlive())return;

threadtest1.start();

}

catch(IllegalThreadStateException illegalthreadexception)

{

System.err.println(illegalthreadexception.toString());

}

}

else if(event.getSource() == runButton2)

{

try

{

threadtest2.start();

}

catch(IllegalThreadStateException illegalthreadexception)

{

System.err.println(illegalthreadexception.toString());

}

}

else if(event.getSource() == interruptButton1)

{

threadtest1.flag=false;

}

else if(event.getSource() == interruptButton2)

{

threadtest2.flag=false;

}

}

}

private class TextFieldHandler1 implements ActionListener

{

public void actionPerformed(ActionEvent event)

{

threadtest1.sleeptime=Long.parseLong(sleepTextField1.getText());

}

}

private class TextFieldHandler2 implements ActionListener

{

public void actionPerformed(ActionEvent event)

{

threadtest2.sleeptime=Long.parseLong(sleepTextField2.getText());

}

}

private class ThreadTest extends Thread

{

final long fixedspeed=500;

public long sleeptime;

private int count=0;

public boolean flag=true;

private String string;

JTextArea textarea;

public ThreadTest(JTextArea textarea,String string,String name)

{

super(name);

this.string=string;

this.textarea=textarea;

}

@Override

public void run()

{

//sleeptime=fixedspeed;

while(count<=string.length()&&flag)

{

SwingUtilities.invokeLater(

new Runnable()

{

public void run()

{

textarea.setText(string.substring(0, count++));

}

}

);

try

{

if(sleeptime<=fixedspeed)

Thread.sleep(fixedspeed);

else

{

Thread.sleep(sleeptime);

sleeptime=fixedspeed;

}

}

catch(InterruptedException interruptedException)

{

System.err.println(interruptedException.toString());

}

}

}

}

public static void main(String args[])

{

ThreadTester1 threadtester=new ThreadTester1();

threadtester.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

}

}

实验要求:2)创建三个线程,每个线程的工作是在自己的界面随机地显示26个英文字母中的一个,可通过界面按钮,临时挂起或恢复各线程的运行。

/*

* To change this template, choose Tools | Templates

* and open the template in the editor.

*/

/**

*

* @author JJ

*/

import java.awt.*;

import javax.swing.*;

import java.awt.event.*;

public class ThreadTester2 extends JFrame

{

protected String alphet="ABCDEFGHIJKLMNOPQRSTUVWXYZ";

private JCheckBox[] blockCBox; //blockCBox1,blockCBox2,blockCBox3;

private JLabel[] threadLabel;//threadLabel1,threadLabel2,threadLabel3;

private Container container;

Thread thread[];

private boolean suspend[];

public ThreadTester2()

{

container=this.getContentPane();

container.setBackground(Color.GRAY);

setnew();

layoutSet();

setSize(400,200);

setVisible(true);

}

private void setnew()

{

blockCBox=new JCheckBox[3];

threadLabel=new JLabel[3];

thread=new Thread[3];

suspend=new boolean[3];

CheckBoxHandler checkboxhandler=new CheckBoxHandler();

for(int i=0;i<3;i++)

{

suspend[i]=false;

blockCBox[i]=new JCheckBox("绾跨▼"+i+"闃诲 ",false);

blockCBox[i].addItemListener(checkboxhandler);

threadLabel[i]=new JLabel();

threadLabel[i].setBackground(Color.blue);

thread[i]=new Thread(new RunnableOBJ(),"Thread"+i);

thread[i].start();

}

}

private class CheckBoxHandler implements ItemListener

{

public void itemStateChanged(ItemEvent event)

{

for(int i=0;i<3;i++)

{

if(event.getSource()==blockCBox[i])

{

suspend[i]=!suspend[i];

if(!suspend[i])

{

synchronized(ThreadTester1.this)

{

ThreadTester1.this.notifyAll();

}

}

else threadLabel[i].setText("闃诲 ");

return;

}

}

}

}

private void layoutSet()

{

this.setLayout(new GridLayout(3,2));

for(int i=0;i<3;i++)

{

container.add(threadLabel[i]);

container.add(blockCBox[i]);

}

}

private int getIndex(Thread t)

{

for(int i=0;i<3;i++)

{

if(t==thread[i])return i;

}

return -1;

}

private class RunnableOBJ implements Runnable

{

public void run()

{

final Thread currentthread=Thread.currentThread();

final int index;

index=getIndex(currentthread);

while(true)

{

try

{

Thread.sleep(500);

synchronized (ThreadTester1.this)//閿佷綇涓荤嚎绋婽hreadTester1瀵硅

薄锛屼唬鐮佸潡鐢ㄤ簬鍐冲畾鏄 惁鎸傝捣褰撳墠绾跨▼

{

while(suspend[index])

{

ThreadTester1.this.wait();

}

}

}

catch(InterruptedException interruptedException)

{

System.err.println(interruptedException.toString());

}

SwingUtilities.invokeLater

(

new Runnable()

{

public void run()

{

int temp=(int)(https://www.wendangku.net/doc/e514602842.html,ng.Math.random()*26);

threadLabel[index].setText("绾跨▼"+index+":"+ThreadTester1.this.alphet.charAt(temp));

}

}

);//end of SwingUtilities.invokeLater

}

}//end of run();

}//end of private class RunnableOBJ implements Runnable

public static void main(String args[])

{

ThreadTester2 threadtester1=new ThreadTester2();

threadtester1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

}

}

实验要求:(3)编写3个线程:各线程分别显示各自的运行时间,第一个线程每隔1秒运行一次,第二线程每隔5秒运行一次,第三个线程每隔10秒运行一次。

/*

* To change this template, choose Tools | Templates

* and open the template in the editor.

*/

//package threadtester2;

/**

*

* @author JJ

*/

import java.awt.*;

import javax.swing.*;

import java.util.Calendar;

public class ThreadTest2 extends JFrame

{

private Container container;

Thread thread[];

private JLabel timelabel[];

Calendar date;

public ThreadTest2()

{

container=this.getContentPane();

container.setBackground(Color.lightGray);

container.setLayout(new GridLayout(1,3));

setnew();

layoutSet();

setSize(600,100);

setVisible(true);

}

private void setnew()

{

timelabel=new JLabel[3];

thread=new Thread[3];

for(int i=0;i<3;i++)

{

timelabel[i]=new JLabel();

thread[i]=new Thread(new RunnableOBJ());

thread[i].start();

}

}

private void layoutSet()

{

for(int i=0;i<3;i++)

{

container.add(timelabel[i]);

}

}

private int getIndex(Thread t)

{

for(int i=0;i<3;i++)

{

if(t==thread[i])return i;

}

return -1;

}

private class RunnableOBJ implements Runnable

{

public void run()

{

final Thread currentthread=Thread.currentThread();

final int index;

index=getIndex(currentthread);

long time=index==0?1000:index==1?5000:10000;

while(true)

{

SwingUtilities.invokeLater

(

new Runnable()

{

public void run()

{

date=Calendar.getInstance();

timelabel[index].setText(date.getTime().toString());

}

}

);//end of SwingUtilities.invokeLater

try

{

Thread.sleep(time);

}

catch(InterruptedException interruptedException)

{

System.err.println(interruptedException.toString());

}

}

}//end of run();

}//end of private class RunnableOBJ implements Runnable

public static void main(String args[])

{

ThreadTest2 threadtester2=new ThreadTest2();

threadtester2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

}

}

java多线程实验报告

java多线程实验报告 篇一:西北农林科技大学java多线程实验报告 实验7 多线程 1.实验目的 (1) 掌握Java多线程的概念和实现方法 (2) 掌握Java多线程的同步问题 2.实验内容 任务一:火车售票 假设有火车票1000张,创建10个线程模拟10个售票点,每个售票点100毫秒买一张票。打印出售票过程,注意使用synchronized确保同一张票只能卖出一次。程序运行结果见左图。 打开Eclipse Tickets.java public class Ticket extends Thread { int ticket =1000; String name =""; public void run(){ while(true){synchronized(name){ if(ticket "第" + Thread.currentThread().getName()+ "售票点卖出了第" + ticket-- + "张票"); } } } }} try{ } catch(InterruptedException e){ }

Thread.sleep(100); Test.java public class Test { } public static void main(String args[]){} Ticket t = new Ticket(); new Thread(t,"1").start(); new Thread(t,"2").start(); new Thread(t,"3").start(); new Thread(t,"4").start(); new Thread(t,"5").start(); new Thread(t,"6").start(); new Thread(t,"7").start(); new Thread(t,"8").start(); new Thread(t,"9").start(); new Thread(t,"10").start(); 任务二:银行存款 假设某家银行,它可接受顾客的汇款,每做一次汇款,便可计算出汇款的总额。现有两个顾客,每人都分3次,每次100元将钱到入。试编写一个程序,模拟实际作业。 程序如下: classCBank { private static int sum=0; public static void add(int n){ inttmp=sum; tmp=tmp+n;// 累加汇款总额 try{ Thread.sleep((int)(10000*Math.random())); //

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

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

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

实验七: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 线程的数据处理

实验2-2windows2000 线程同步

实验2 并发与调度 2.2 Windows 2000线程同步 (实验估计时间:120分钟) 背景知识 实验目的 工具/准备工作 实验内容与步骤 背景知识 Windows 2000提供的常用对象可分成三类:核心应用服务、线程同步和线程间通讯。其中,开发人员可以使用线程同步对象来协调线程和进程的工作,以使其共享信息并执行任务。此类对象包括互锁数据、临界段、事件、互斥体和信号等。 多线程编程中关键的一步是保护所有的共享资源,工具主要有互锁函数、临界段和互斥体等;另一个实质性部分是协调线程使其完成应用程序的任务,为此,可利用内核中的事件对象和信号。 在进程内或进程间实现线程同步的最方便的方法是使用事件对象,这一组内核对象允许一个线程对其受信状态进行直接控制 (见表4-1) 。 而互斥体则是另一个可命名且安全的内核对象,其主要目的是引导对共享资源的访问。拥有单一访问资源的线程创建互斥体,所有想要访问该资源的线程应该在实际执行操作之前获得互斥体,而在访问结束时立即释放互斥体,以允许下一个等待线程获得互斥体,然后接着进行下去。 与事件对象类似,互斥体容易创建、打开、使用并清除。利用CreateMutex() API 可创建互斥体,创建时还可以指定一个初始的拥有权标志,通过使用这个标志,只有当线程完成了资源的所有的初始化工作时,才允许创建线程释放互斥体。

为了获得互斥体,首先,想要访问调用的线程可使用OpenMutex() API来获得指向对象的句柄;然后,线程将这个句柄提供给一个等待函数。当内核将互斥体对象发送给等待线程时,就表明该线程获得了互斥体的拥有权。当线程获得拥有权时,线程控制了对共享资源的访问——必须设法尽快地放弃互斥体。放弃共享资源时需要在该对象上调用ReleaseMute() API。然后系统负责将互斥体拥有权传递给下一个等待着的线程(由到达时间决定顺序) 。 实验目的 在本实验中,通过对事件和互斥体对象的了解,来加深对Windows 2000线程同步的理解。 1) 回顾系统进程、线程的有关概念,加深对Windows 2000线程的理解。 2) 了解事件和互斥体对象。 3) 通过分析实验程序,了解管理事件对象的API。 4) 了解在进程中如何使用事件对象。 5) 了解在进程中如何使用互斥体对象。 6) 了解父进程创建子进程的程序设计方法。 工具/准备工作 在开始本实验之前,请回顾教科书的相关内容。 您需要做以下准备: 1) 一台运行Windows 2000 Professional操作系统的计算机。 2) 计算机中需安装Visual C++ 6.0专业版或企业版。 实验内容与步骤 1. 事件对象 2. 互斥体对象 1. 事件对象 清单2-1程序展示了如何在进程间使用事件。父进程启动时,利用CreateEvent() API创建一个命名的、可共享的事件和子进程,然后等待子进程向事件发出信号并终止父进程。在创建时,子进程通过OpenEvent() API打开事件对象,调用SetEvent() API使其转化为已接受信号状态。两个进程在发出信号之后几乎立即终止。 步骤1:登录进入Windows 2000 Professional。 步骤2:在“开始”菜单中单击“程序”-“Microsoft Visual Studio 6.0”–“Microsoft Visual C++ 6.0”命令,进入Visual C++窗口。

进程的同步实验报告汇总

操作系统 实验报告 哈尔滨工程大学 计算机科学与技术学院

一、实验概述 1. 实验名称 进程的同步 2. 实验目的 ⑴使用EOS的信号量,编程解决生产者 消费者问题,理解进程同步的意义。 ⑵调试跟踪EOS信号量的工作过程,理解进程同步的原理。 ⑶修改EOS的信号量算法,使之支持等待超时唤醒功能(有限等待),加深理解进程同步的原理。 3. 实验类型 验证+设计 4. 实验内容 ⑴准备实验 ⑵使用EOS的信号量解决生产者-消费者问题 ⑶调试EOS信号量的工作过程 ①创建信号量 ②等待释放信号量 ③等待信号量(不阻塞) ④释放信号量(不唤醒) ⑤等待信号量(阻塞) ⑥释放信号量(唤醒) ⑷修改EOS的信号量算法 二、实验环境 WindowsXP + EOS集成实验环境 三、实验过程 1. 设计思路和流程图

图4-1.整体试验流程图

图4-2.Main 函数流程图、生产者消费、消费者流程图 2. 算法实现 3. 需要解决的问题及解答 (1). 思考在ps/semaphore.c 文件内的PsWaitForSemaphore 和PsReleaseSemaphore 函数中,为什么要使用原子操作?

答:在执行等待信号量和释放信号量的时候,是不允许cpu响应外部中断的,如果此时cpu响应了外部中断,会产生不可预料的结果,无法正常完成原子操作。 (2). 绘制ps/semaphore.c文件内PsWaitForSemaphore和PsReleaseSemaphore函数的流程图。 (3).P143生产者在生产了13号产品后本来要继续生产14号产品,可此时生产者为什么必须等待消费者消费了4号产品后,才能生产14号产品呢?生产者和消费者是怎样使用同步对象来实现该同步过程的呢? 答:这是因为临界资源的限制。临界资源就像产品仓库,只有“产品仓库”空闲生产者才能生产东西,有权向里面放东西。所以它必须等到消费者,取走产品,“产品空间”(临界资源)空闲时,才继续生产14号产品。 (4). 根据本实验3.3.2节中设置断点和调试的方法,自己设计一个类似的调试方案来验证消费者线程在消费24号产品时会被阻塞,直到生产者线程生产了24号产品后,消费者线程才被唤醒并继续执行的过程。 答:可以按照下面的步骤进行调试 (1) 删除所有的断点。 (2) 按F5启动调试。OS Lab会首先弹出一个调试异常对话框。 (3) 在调试异常对话框中选择“是”,调试会中断。 (4) 在Consumer函数中等待Full信号量的代码行(第173行)WaitForSingleObject(FullSemaphoreHandle, INFINITE); 添加一个断点。 (5) 在“断点”窗口(按Alt+F9打开)中此断点的名称上点击右键。 (6) 在弹出的快捷菜单中选择“条件”。 (7) 在“断点条件”对话框(按F1获得帮助)的表达式编辑框中,输入表达式“i == 24”。 (8) 点击“断点条件”对话框中的“确定”按钮。 (9) 按F5继续调试。只有当消费者线程尝试消费24号产品时才会在该条件断点处中断。 4. 主要数据结构、实现代码及其说明 修改PsWaitForSemaphore函数 if (Semaphore->Count>0){ Semaphore->Count--; flag=STATUS_SUCCESS; }//如果信号量大于零,说明尚有资源,可以为线程分配 else flag=PspWait(&Semaphore->WaitListHead, Milliseconds); KeEnableInterrupts(IntState); // 原子操作完成,恢复中断。 return flag; }//否则,说明资源数量不够,不能再为线程分配资源,因此要使线程等待 修改PsReleaseSemaphore函数 if (Semaphore->Count + ReleaseCount > Semaphore->MaximumCount) {

实验一 进程与线程

实验:进程与线程 一、实验目的 通过函数调用掌握进程之间的通信。 体会线程的存在,了解线程与进程的关系。 二、实验环境 PC+Win7操作系统 三、实验方法和实验步骤 1.准备工作 打开VC++6.0环境。 2.在程序编辑区内输入程序,实现两个数互换。 3. 在VC环境下建立一个控制台应用程序P1。系统启动一个进程(因为支持线程,OS会在进程中主动创建一个主线程)来运行该程序。输出该进程的ID号、以及该进程下面主线程的ID号。多运行几次,观察结果。 四、实验结果

补充:在VC环境下建立一个控制台应用程序P1。系统启动一个进程(因为支持线程,OS会在进程中主动创建一个主线程)来运行该程序。 在进程中,我们自己再创建一个子线程(子线程1),该子线程做的事情很简单,就是让它不停地输出如下信息: 子线程1正在运行第1次,其进程的ID号=~, 子线程1的ID号=~ 子线程1正在运行第2次,其进程的ID号=~, 子线程1的ID号=~ 。。。。。。 。。。。。。 子线程1正在运行第20次,其进程的ID号=~, 子线程1的ID号=~ 只要启动了一个子线程,实际上系统中是主线程和子线程1在并发执行。 主线程的功能是输出这样形式的内容: 主线程正在运行第1次,其进程的ID号=~,主线程的ID号=~ 主线程正在运行第2次,其进程ID号=~, 主线程的ID号=~ 。。。。。。 。。。。。。 主线程正在运行第20次,其进程ID号=~, 主线程的ID号=~ 多运行几次,观察主线程和子线程并发调动的次序。每次调度都一样吗?为什么?进程ID、主线程ID和子线程ID每次都一样吗? 体会操作系统中并发的异步性。 程序代码如下: #include #include DWORD WINAPI Thread1(LPVOID lpparameter){ int i; for(i=1;i<=20;i++){ printf("子线程1在运行中,它正在运行第%d times,所属进程的ID号=%ld, 本线程的ID号=%ld\n",i,GetCurrentProcessId(),GetCurrentThreadId());} return 0;} int main(){ int j; printf("一个进程在运行中\n"); printf("主线程在运行中\n"); HANDLE hThread1=CreateThread(NULL,0,Thread1,NULL,0,NULL); for(j=1;j<=20;j++){ printf("主线程正在运行第%d次;进程的ID号=%ld,线程ID号=%ld\n", j,GetCurrentProcessId(),GetCurrentThreadId()); Sleep(500); } return 0; } 多次运行的结果显示,每次调度是不一样的,因为操作系统中程序并发运行时的异步性原则,进程ID、主线程ID和子线程ID每次也都是不一样的。

实验2 线程同步机制

实验2 线程同步机制 一、实验目的: 通过观察共享数据资源但不受控制的两个线程的并发运行输出结果,体会同步机制的必要性和重要性。然后利用现有操作系统提供的同步机制编程实现关于该两个线程的有序控制,同时要求根据同步机制的Peterson软件解决方案尝试自己编程实现同步机制和用于同一问题的解决,并基于程序运行时间长短比较两种同步机制。 二、实验设计 I基于给定银行账户间转账操作模拟代码作为线程执行代码,在主线程中创建两个并发线程,编程实现并观察程序运行结果和予以解释说明。 II利用Windows互斥信号量操作函数解决上述线程并发问题,并分析、尝试和讨论线程执行体中有关信号量操作函数调用的正确位置。 III根据同步机制的Peterson软件解决方案尝试自己编程实现线程同步机制和用于上述线程并发问题的解决,并基于程序运行时间长短

将其与基于Windows互斥信号量的线程同步机制的效率展开比较。其间,可规定线程主体代码循环执行1000000次 三、源程序清单和说明 1未利用互斥信号量 #include #include #include int nAccount1 = 0, nAccount2 = 0; int nLoop = 0; int nTemp1, nTemp2, nRandom; DWORD WINAPI ThreadFunc(HANDLE Thread) { do { nTemp1 = nAccount1; nTemp2 = nAccount2; nRandom = rand(); nAccount1 = nTemp1 + nRandom; nAccount2 = nTemp2 - nRandom; nLoop++; } while ((nAccount1 + nAccount2) == 0); printf("循环次数为%d\n", nLoop); return 0; } int main() { HANDLE Thread[2]; Thread[0] = CreateThread(NULL,0,ThreadFunc,NULL,0,NULL); Thread[1] = CreateThread(NULL,0,ThreadFunc,NULL,0,NULL); WaitForMultipleObjects(2,Thread,TRUE,INFINITE); CloseHandle(Thread); return 0; }

实验一 和实验二

实验一熟悉Windows2000/XP中的进程和线程 一、实验目的 1、熟悉Windows2000/XP中任务管理器的使用。 2、通过任务管理器识别操作系统中的进程和线程的相关信息。 3、掌握利用spy++.exe来察看Windows中各个任务的更详细信息。 二、实验理论基础 1、实验理论基础: (1)操作系统中的进程和线程的概念; (2)进程PCB的各项指标含意; (3)操作系统中的进程和线程的概念; (4)进程的各种控制; 三、实验内容与步骤 1、启动操作系统自带的任务管理器: 方法:直接按组合键Ctrl+Alt+Del,或者是在点击任务条上的“开始”“运行”,并输入“taskmgr.exe”。如下图所示:

2、调整任务管理器的“查看”中的相关设置,显示关于进程的以下各项信息, 并完成下表(填满即可): 表一:统计进程的各项主要信息

3、从桌面启动办公软件“Word”,在任务管理器中找到该软件的登记,并将其结 束掉。再从任务管理器中分别找到下列程序:winlogon.exe、lsass.exe、csrss.exe、smss.exe,试着结束它们,观察到的反应是无法中止进程,原因是该程序为关键系统进程,任务管理器无法结束进程。 4、在任务管理器中找到进程“explorer.exe”,将之结束掉,并将桌面上你打开 的所有窗口最小化,看看你的计算机系统起来什么样的变化桌面所有的快捷图标消失,任务栏消失、得到的结论是这个进程用于显示桌面上的图标和开始菜单(说出explorer.exe进程的作用)。 5、运行“spy++.exe”应用软件,点击按钮“”,切换到进程显示栏上,查看进程“explorer.exe”的各项信息,并填写下表: 表二:统计线程的各项信息 进程:explorer.exe 中的各个线程

实验三 进程同步的经典算法

实验三进程同步的经典算法 背景知识 Windows提供的常用对象可分成三类:核心应用服务、线程同步和线程间通讯。其中,开发人员可以使用线程同步对象来协调线程和进程的工作,以使其共享信息并执行任务。此类对象包括互锁数据、临界段、事件、互斥体和信号等。 多线程编程中关键的一步是保护所有的共享资源,工具主要有互锁函数、临界段和互斥体等;另一个实质性部分是协调线程使其完成应用程序的任务,为此,可利用内核中的事件对象和信号。 在进程内或进程间实现线程同步的最方便的方法是使用事件对象,这一组内核对象允许一个线程对其受信状态进行直接控制(见表3-1) 。 而互斥体则是另一个可命名且安全的内核对象,其主要目的是引导对共享资源的访问。拥有单一访问资源的线程创建互斥体,所有想要访问该资源的线程应该在实际执行操作之前获得互斥体,而在访问结束时立即释放互斥体,以允许下一个等待线程获得互斥体,然后接着进行下去。 与事件对象类似,互斥体容易创建、打开、使用并清除。利用CreateMutex() API可创建互斥体,创建时还可以指定一个初始的拥有权标志,通过使用这个标志,只有当线程完成了资源的所有的初始化工作时,才允许创建线程释放互斥体。 为了获得互斥体,首先,想要访问调用的线程可使用OpenMutex() API来获得指向对象的句柄;然后,线程将这个句柄提供给一个等待函数。当内核将互斥体对象发送给等待线程时,就表明该线程获得了互斥体的拥有权。当线程获得拥有权时,线程控制了对共享资源的访问——必须设法尽快地放弃互斥体。放弃共享资源时需要在该对象上调用ReleaseMute() API。然后系统负责将互斥体拥有权传递给下一个等待着的线程(由到达时间决定顺序) 。

进程(线程)的同步与互斥实验报告

操作系统实验报告 课程名称操作系统实验名称进程(线程)的同步与互斥成绩 学生姓名作业君专业软件工程班级、学号 同组者姓名无实验日期2020 一、实验题目:进程(线程)的同步与互斥 二、实验目的: 自行编制模拟程序,通过形象化的状态显示,加深理解进程的概念、进程之间的状态转换及其所带来的PCB内容、组织的变化,理解进程与其PCB间的一一对应关系。1.掌握基本的同步与互斥算法,理解生产者消费者模型。 2.学习使用Windows中基本的同步对象,掌握相关API的使用方法。 3.了解Windows中多线程的并发执行机制,实现进程的同步与互斥 三、实验内容与要求: 1.实验内容 以生产者/消费者模型为依据,在Windows 环境下创建一个控制台进程,在该进程中创建n个线程模拟生产者和消费者,实现进程(线程)的同步与互斥。 2.实验要求 学习并理解生产者/消费者模型及其同步/互斥规则; 学习了解Windows同步对象及其特性; 熟悉实验环境,掌握相关API的使用方法; 设计程序,实现生产者/消费者进程(线程)的同步与互斥; 四、算法描述(含数据结构定义)或流程图 #include #include #include #include #include #include using namespace std;

#define MAX_THREAD_NUM 64 //最大线程数 #define INTE_PER_SEC 1000 //延迟时间的毫秒值 const int SIZE_OF_BUFFER = 10; //缓冲区长度 int ProductID = 0; //产品号 int ConsumeID = 0; //将被消耗的产品号 int in = 0; //产品进缓冲区时的缓冲区下标 int out = 0; //产品出缓冲区时的缓冲区下标 bool running = true; //判断程序能否继续执行的逻辑值 int g_buffer[SIZE_OF_BUFFER]; //缓冲区是个循环队列 HANDLE g_hMutex; //公有信号量,用于线程间的互斥HANDLE g_hFullSemaphore; //生产者的私有信号量,当缓冲区满时迫使生产者等待 HANDLE g_hEmptySemaphore; //消费者的私有信号量,当缓冲区空时迫使消费者等待 //定义一个结构体用于存储线程的信息 struct ThreadInfo { int serial; //线程号 char entity; //线程类别(生产者或消费者) double delay; //等待时间 double persist; //操作时间 }; //生产者 void Producer(void* p) { //定义变量用于存储当前线程的信息 DWORD m_delay; DWORD m_persist; int m_serial; //从参数中获得信息 m_serial = ((ThreadInfo*)(p))->serial; m_delay = (DWORD)(((ThreadInfo*)(p))->delay * INTE_PER_SEC); m_persist = (DWORD)(((ThreadInfo*)(p))->persist * INTE_PER_SEC); while (running) { //P操作 cout << "生产者线程 " << m_serial << " 请求生产." << endl; WaitForSingleObject(g_hEmptySemaphore, INFINITE);

查看程序的进程和线程实验报告

查看程序的进程和线程实验报告 篇一:程序实验2:11-多线程编程---实验报告 程序实验二:11-多线程编程实验 专业班级实验日期 5.21 姓名学号实验一(p284:11-thread.c) 1、软件功能描述 创建3个线程,让3个线程重用同一个执行函数,每个线程都有5次循环,可以看成5个小任务,每次循环之间会有随即等待时间(1-10s)意义在于模拟每个任务到达的时间是随机的没有任何的特定规律。 2、程序流程设计 3.部分程序代码注释(关键函数或代码) #include #include #include #define T_NUMBER 3 #define P_NUMBER 5 #define TIME 10.0

void *thrd_func(void *arg ) { (本文来自:https://www.wendangku.net/doc/e514602842.html, 小草范文网:查看程序的进程和线程实验报告) int thrd_num=(int)arg; int delay_time =0; int count =0; printf("Thread %d is staraing\n",thrd_num); for(count=0;count { delay_time =(int)(rand()*TIME/(RAND_MAX))+1; sleep(delay_time); printf("\tTH%d:job%d delay =%d\n",thrd_num,count,delay_time); } printf("%d finished\n",thrd_num); pthread_exit(NULL); } int main()

操作系统实验线程同步

实验2:线程同步 一、实验目的 (1)掌握Windows2000环境下,线程同步。 (2)熟悉Windows2000提供的线程同步与互斥API。 (3)用Windows2000提供的线程同步与互斥API解决实际问题 (producer-consumer)。 二、实验内容 生产者与消费者问题的实现。在Windows 2000环境下,创建一组“生产者”线程和一组“消费者”线程,并建立一个长度为N的全局数组作为共享缓冲区。“生产者”向缓冲区输入数据,“消费者”从缓冲区读出数据。当缓冲区满时,“生产者”必须阻塞,等待“消费者”取走缓冲区数据后将其唤醒。当缓冲区空时,“消费者”阻塞,等待“生产者”生产了产品后将其唤醒。试用信号量实现“生产者”与“消费者”线程之间的同步。 三、实验环境 (1)使用的操作系统及版本。 Windows xp professional (2)使用的编译系统及版本。 Visual c++ 6.0 四、实验步骤 1.等待一个对象(相当于p操作) WaitForSingleObject用于等待一个对象。它等待的对象可以为: Change notification:变化通知。 Console input:控制台输入。 Event:事件。 Job:作业。 Mutex:互斥信号量。 Process:进程。 Semaphore:计数信号量。

Thread:线程。 Waitable timer:定时器。 返回值: 如果成功返回,其返回值说明是何种事件导致函数返回。 访问描述 WAIT_ABANDONED 等待的对象是一个互斥(mutex)对象,该互斥对 象没有被拥有它的线程释放,它被设置为不能被唤 醒。 WAIT_OBJECT_0 指定对象被唤醒。 WAIT_TIMEOUT 超时。 2.创建信号量 CreateSemaphore用于创建一个信号量。 返回值: 信号量创建成功,将返回该信号量的句柄。如果给出的信号量名是系统已经存在的信号量,将返回这个已存在信号量的句柄。如果失败,系统返回NULL,可以调用函数GetLastError查询失败的原因。 3.打开信号量 OpenSemaphore用于打开一个信号量。 返回值: 信号量打开成功,将返回该信号量的句柄。如果失败,系统返回NULL,可以调用函数GetLastError查询失败的原因。 4.增加信号量的值 ReleaseSemaphore用于增加信号量的值。 返回值: 如果成功,将返回一个非0值。如果失败,系统返回0,可以调用函数GetLastError 查询失败的原因。 方法一: 程序代码: #include #include

实验四 同步与互斥 Linux实验报告

实验四同步与互斥 【实验目的和要求】 1、掌握进程(线程)的同步与互斥。 2、掌握生产者消费者问题的实现方法。 3、掌握多线程编程方法。 【实验内容】 实现生产者消费者问题 1、有一个仓库,生产者负责生产产品,并放入仓库,消费者会从仓库中拿走产品(消费)。 2、仓库中每次只能入一个(生产者或消费者)。 3、仓库中可存放产品的数量最多10个,当仓库放满时,生产者不能再放入产品。 4、当仓库空时,消费者不能从中取出产品。 5、生产、消费速度不同。 【实验原理】 1、信号量mutex提供对缓冲池访问的互斥要求并初始化为1,信号量empty和 full分别用来表示空缓冲项和满缓冲项的个数,信号量empty初始化为n,信号量full初始化为0。 2、定义如下结构及数据: 定义缓冲区内的数据类型:typedef int buffer_item; 缓冲区:buffer_item buffer[BUFFER_SIZE];

对缓冲区操作的变量:int in,out; 信号量mutex提供了对缓冲池访问的互斥要求:pthread_mutex_t mutex; 信号量empty和full分别表示空缓冲顶和满缓冲顶的个数:sem_t empty,full; 可以设定生产者的生产速度及消费者的消费速度:int pro_speed,con_speed; 对缓冲区操作的自增函数:#define inc(k) if(k < BUFFER_SIZE) k = k+1;else k=0 3、并定义了如下实现问题的函数模块: 将生产的产品放入缓冲区: int insert_item(buffer_item item) 从缓冲区内移走一个产品: int remove_item(buffer_item *item) 生产者进程:void *producer(void *param) 消费者进程:void *consumer(void *param) 生产者结构进程消费者结构进程 【程序代码】 //sx.c #include

实验二-Linux进程、线程及编程

实验二Linux进程、线程及编程实验 一、实验目的 1、通过编写一个完整的守护进程,掌握守护进程编写和调试的方法 2、进一步熟悉如何编写多进程程序 二、实验环境 硬件:PC机一台,JXARM9-2410教学实验平台。 软件:Windows98/XP/2000系统,虚拟机环境下的Linux系统。 三、预备知识 1、fork() fork()函数用于从已存在的进程中创建一个新进程。新进程称为子进程,而原进程称为父进程。使用fork()函数得到的子进程是父进程的一个复制品,它从父进程处继承了整个进程的地址空间,包括进程上下文、代码段、进程堆栈、存信息、打开的文件描述符、信号控制设定、进程优先级、进程组号、当前工作目录、根目录、资源限制和控制终端等,而子进程所独有的只有它的进程号、资源使用和计时器等 2、exit()和_exit()的区别 _exit()函数的作用最为简单:直接使进程停止运行,清除其使用的存空间,并销毁其在核中的各种数据结构; exit()函数则在这些基础上作了一些包装,在执行退出之前加了若干道工序。 exit()函数在调用exit系统调用之前要检查文件的打开情况,把文件缓冲区中的容写回文件,就是图中的"清理I/O缓冲"一项。 3、wait()和waitpid() wait()函数是用于使父进程(也就是调用wait()的进程)阻塞,直到一个子进程结束或者该进程接到了一个指定的信号为止。如果该父进程没有子进程或者他的子进程已经结束,则wait()就会立即返回。 四、实验容 在该实验中,读者首先创建一个子进程1(守护进程),然后在该子进程中新建一个子进程2,该子进程2暂停10s,然后自动退出,并由子进程1收集子线程退出的消息。在这里,子进程1和子进程2的消息都在系统日志文件(例如“/var/log/messages”,日志文件的全路径名因版本的不同可能会有所不同)中输出。在向日志文件写入消息之后,守护进程(子进程1)循环暂停,其间隔时间为10s。 五、实验步骤

实验1编程实现进程(线程)同步和互斥

实验1编程实现进程(线程)同步和互斥 一、实验目的 ①通过编写程序实现进程同步和互斥,使学生掌握有关进程(线程)同步与 互斥的原理,以及解决进程(线程)同步和互斥的算法,从而进一步巩固进程(线程)同步和互斥 ②等有关的内容。 ③了解Windows2000/XP中多线程的并发执行机制,线程间的同步和互斥。 ④学习使用Windows2000/XP中基本的同步对象,掌握相应的 ⑤API函数。 ⑥掌握进程和线程的概念,进程(线程)的控制原语或系统调用的使用。 ⑦掌握多道程序设计的基本理论、方法和技术,培养学生多道程序设计的能 力。 二、实验内容 在Windows XP、Windows 2000等操作系统下,使用的VC、VB、java或C 等编程语言,采用进程(线程)同步和互斥的技术编写程序实现生产者消费者问题或哲学家进餐问题或读者-写者问题或自己设计一个简单进程(线程)同步和互斥的实际问题。 三、实验要求 ①经调试后程序能够正常运行。 ②采用多进程或多线程方式运行,体现了进程(线程)同步和互斥的关系。 ③程序界面美观。 四、实验步骤、过程 让写者与读者、读者与读者之间互斥的访问同一数据集,在无写者进程到来时各读者可同时的访问数据集,在读者和写者同时等待时写者优先唤醒。设置两个全局变量readcount 和writecount来记录读者与写者的数目,设置了3个信号量。h_mutex1表示互斥对象对阻塞在read这一个过程实现互斥,h_mutex2实现全局变量readcount操作上的互斥,h_mutex3实现对全局变量writecount的互斥访问。设置了两个临界区,为了实现写者优先,用了临界区read。数据结构:(1)用了两个临界区(2)自定义结构ThreadInfo记录一条线程信息,多个线程对应一个ThreadInfo数组。(3)设置了互斥量h_mutex1,实现了互斥对象对阻

操作系统--进程和线程实验报告

一.进程的创建 1.编辑源程序。 2. 编辑结果如下。 3.编译和运行程序。 4.运行解释结果 在语句p1=fork()之前,只有一个进程在执行这段代码,但在这条语句之后,就变成两个进程在执行了.这两个进程的几乎完全相同,将要执行的下一条语句都是if(p1==0). 而fork函数有三种返回值。(1)在父进程中,fork返回新创建子进程的进程ID; (2)在子进程中,fork返回0; (3)如果出现错误,fork返回一个负值; 所以,子进程中p1==0,输出I am child。父进程p1>0,输出I am parent。

1.编辑源程序。 2.编辑结果如下。 3.编译和运行程序。 4. 运行解释结果 在语句p1=fork()之前,只有父进程执行,putchar(‘x’)语句将x放入父进程的缓冲区。当成功创建子进程后,子进程复制父进程的缓冲区。接着子进程运行输出xby,父进程输出xay。

1.编辑源程序。 2.编辑结果如下。 3.编译和运行程序。 4. 运行解释结果 在语句p1=fork()之前,只有父进程执行,putchar(‘x’)语句将x放入父进程的缓冲区。当成功创建子进程后,子进程复制父进程的缓冲区。接着子进程输出b后,执行exit(0)系统调用终止执行。父进程输出a 后继续输出y。所以父进程输出xay而子进程输出xb。

1.编辑源程序。 2.编辑结果如下。 3.编译和运行程序。 4. 运行解释结果 语句while(p1=fork()==-1)创建了子进程和父进程。父进程执行到wait()时,等待子进程的终止信号,当子进程执行完exit(0)后,父进程才继续执行。实现了父进程等待子进程。

实验二进程同步实验

实验二进程同步 一、实验目的: 掌握基本的同步算法,理解经典进程同步问题的本质;学习使用Linux的进程同步机制,掌握相关API的使用方法;能利用信号量机制,采用多种同步算法实现不会发生死锁的哲学家进餐程序。 二、实验平台: 虚拟机:VMWare9以上 操作系统:以上 编辑器:Gedit | Vim 编译器:Gcc 三、实验内容: (1)以哲学家进餐模型为依据,在Linux控制台环境下创建5个进程,用semget函数创建一个信号量集(5个信号量,初值为1),模拟哲学家的思考和进餐行为:每一位哲学家饥饿时,先拿起左手筷子,再拿起右手筷子;筷子是临界资源,为每一支筷子定义1个互斥信号量;想拿到筷子需要先对信号量做P操作,使用完释放筷子对信号量做V操作。 伪代码描述: semaphore chopstick[5]={1,1,1,1,1}; ?第i位哲学家的活动可描述为: do{ printf("%d is thinking\n",i); printf("%d is hungry\n",i); wait(chopstick[i]); 当哲学家的左、右两只筷子均可用时,才允许他拿起筷子进餐;b.至多只允许有4位哲学家同时去拿左边的筷子,最终能保证至少有一位哲学家能够进餐;c.规定奇数号哲学家先拿起他左手的筷子,然后再拿起他右手的筷子,而偶数号哲学家则先拿起他右手的筷子,然后再拿起他左手的筷子。方法a在示例程序中给出,请用方法b和c写出不会发生死锁的哲学家进餐程序。 (3)设计程序,实现生产者/消费者进程(线程)的同步与互斥。在该程序中创建4个进程(或线程)模拟生产者和消费者,实现进程(线程)的同步与互斥。

实验二 编程实现进程(线程)同步和互斥

《操作系统》实验内容 实验二编程实现进程(线程)同步和互斥 1.实验的目的 (1)通过编写程序实现进程同步和互斥,使学生掌握有关进程(线程)同步与互斥的原理,以及解决进程(线程)同步和互斥的算法,从而进一步巩固进程(线程)同步和互斥等有关的内容。 (2)了解Windows2000/XP中多线程的并发执行机制,线程间的同步和互斥。 (3)学习使用Windows2000/XP中基本的同步对象,掌握相应的API函数。 (4)掌握进程和线程的概念,进程(线程)的控制原语或系统调用的使用。 (5)掌握多道程序设计的基本理论、方法和技术,培养学生多道程序设计的能力。2.实验内容 在Windows XP、Windows 2000等操作系统下,使用的VC、VB、java或C等编程语言,采用进程(线程)同步和互斥的技术编写程序实现生产者-消费者问题或哲学家进餐问题或读者-写者问题或自己设计一个简单进程(线程)同步和互斥的实际问题。 3.实验要求 (1)经调试后程序能够正常运行。 (2)采用多进程或多线程方式运行,体现了进程(线程)同步和互斥的关系。 (3)程序界面美观。 4.实验步骤 (1)需求分析:了解基本原理,确定程序的基本功能,查找相关资料,画出基本的数据流图; (2)概要设计:确定程序的总体结构、模块关系和总体流程; (3)详细设计:确定模块内部的流程和实现算法; (4)上机编码和调试; (5)运行测试; (6)编写实验报告。 5.实验报告要求 格式符合《实验报告格式》书;书写规范,排版美观,有较强的文字表达能力,能够正确地表达自己的思想,图表符合规范。 6.实验说明 本实验分两次进行,每次要求填写一份实验报告,报告中的实验名分别为:编程实现进程同步和互斥1和编程实现进程同步和互斥2,其他内容依据实验进度具体填写。

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 #include #include

相关文档
相关文档 最新文档