操作系统实验:进程同步控制

这篇具有很好参考价值的文章主要介绍了操作系统实验:进程同步控制。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

文章目录

前言

一、开发语言及实验平台或实验环境

二、实验目的

三、实验要求

四、实验原理

五、实验过程

六、代码详解

七、diy一下

总结


前言

计算机操作系统是一门研究计算机系统的基本原理和设计方法的课程,它涉及到计算机系统的结构、功能、性能和管理等方面。操作系统实验是操作系统课程的重要组成部分,它可以帮助加深对操作系统理论知识的理解,提高分析和解决实际问题的能力,培养动手实践的能力和创新精神。

进程同步控制是操作系统实验中的一个重要内容,它主要涉及到进程间的协作、竞争和互斥等问题,以及如何使用信号量、管程、消息传递等机制来实现进程同步控制的方法。本实验旨在让学生通过编写和运行一些典型的进程同步控制程序,掌握进程同步控制的基本概念、原理和技术,熟悉操作系统提供的进程同步控制接口和工具,增强对操作系统内核功能的认识和理解。


一、开发语言及实验平台或实验环境

C++/JAVA

Turbo C / Microsoft Visual Studio 6.0 /  Microsoft Visual Studio .NET 2010

本文中使用的语言是Java,使用的平台是idea

二、实验目的

(1)加强对进程概念的理解,尤其是对进程的同步与互斥机制的理解

(2)分析进程竞争资源的现象,学习解决进程互斥与同步的方法。

三、实验要求

(1)理解利用进程控制机制;

(2)理解利用信号量进行进程同步控制原理;

(3)使用某种编程语言进行模拟实现生产者-消费者进程。

四、实验原理

(注意:这个仅是个例子,仅供参考)

生产者-消费者问题描述的是:有一群生产者进程在生产产品,并将这些产品提供给消费者进程去消费。为使生产者进程与消费者进程能够并发执行,在两者之间设置了一个具有n个缓冲区的缓冲池,生产者进程将它所生产的产品放入一个缓冲区中;消费者进程可以从一个缓冲区中取走产品去消费。尽管所有的生产者和消费者进程都是以异步方式运行的,但它们之间必须保持同步,即不允许消费者进程到一个空缓冲区去取产品;也不允许生产者进程向一个已经装满产品的缓冲区中投放产品。

这是一个同步与互斥共存的问题。

生产者—消费者问题是一个同步问题。即生产者和消费者之间满足如下条件:

(1) 消费者想接收数据时,有界缓冲区中至少有一个单元是满的。

(2) 生产者想发送数据时,有界缓冲区中至少有一个单元是空的。

五、实验过程

浅画一个流程图:

操作系统实验进程同步,计算机操作系统实验,java,c语言,idea,windows

 

示例代码如下:

class Q
{
String name;
int num=0;
int size=10;
}

class Producer implements Runnable
{
Q q;
Producer(Q q)
{
this.q = q;
this.q.name="producer";
}

public void run()
{
while(true)
{

synchronized(q)
{
if(q.num<q.size)
{
q.num++;
System.out.println("producer已生产第:"+q.num+"个产品!");
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
q.notify();
}
else
{
try {
System.out.println("producer stop!");
q.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}


class Consumer implements Runnable
{
Q q;
Consumer(Q q)
{
this.q = q;
this.q.name="consumer";
}

public void run()
{
while(true)
{
synchronized(q)
{
if(q.num>0)
{
System.out.println("consumer要消费第:"+q.num+"个产品!");
q.num--;
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
q.notifyAll();
}
else
{
try {
System.out.println("consumer stop!");
q.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
public class project
{
public static void main(String[] args)
{
Q q = new Q();
new Thread(new Producer(q)).start();
new Thread(new Consumer(q)).start();
}
}

效果如下:

操作系统实验进程同步,计算机操作系统实验,java,c语言,idea,windows

操作系统实验进程同步,计算机操作系统实验,java,c语言,idea,windows

六、代码详解

  这段代码定义了三个类:QProducerConsumer

Q类定义了一个名为name的字符串变量,一个名为num的整数变量,初始值为0,以及一个名为size的整数变量,初始值为10。

Producer类实现了Runnable接口,它有一个构造函数,该构造函数接受一个Q类型的参数。在构造函数中,它将传递的参数赋值给成员变量q,并将其成员变量name设置为“producer”。

Producer类中,还定义了一个名为run()的方法。这个方法是一个无限循环,在循环中,它使用synchronized(q)块来确保一次只有一个线程可以访问共享的Q对象。在synchronized(q)块中,它首先检查共享的Q对象中的变量num是否小于其变量size。如果是,则将其变量num增加1,并打印一条消息表示生产了一个产品。然后它调用线程休眠100毫秒,并使用q.notify()唤醒等待该对象锁的线程。

如果共享的

Q对象中的变量num不小于其变量size,则打印一条消息表示生产者停止,并调用q.wait()使当前线程等待,直到其他线程调用该对象的notify()notifyAll()方法。

Consumer类也实现了Runnable接口,它有一个构造函数,该构造函数接受一个Q类型的参数。在构造函数中,它将传递的参数赋值给成员变量q,并将其成员变量name设置为“consumer”。

Consumer类中,也定义了一个名为run()的方法。这个方法也是一个无限循环,在循环中,它也使用synchronized(q)块来确保一次只有一个线程可以访问共享的Q对象。在synchronized(q)块中,它首先检查共享的Q对象中的变量num是否大于0。如果是,则打印一条消息表示要消费一个产品,并将其变量num减少1。然后它调用线程休眠100毫秒,并使用

q.notifyAll()唤醒等待该对象锁的所有线程。

如果共享的Q对象中的变量num不大于0,则打印一条消息表示消费者停止,并调用q.wait()使当前线程等待,直到其他线程调用该对象的notify()notifyAll()方法。

最后,project类定义了一个名为main()的方法。在这个方法中,它创建了一个新的Q对象,并使用这个对象创建了一个新的Producer对象和一个新的Consumer对象。然后它分别为这两个对象创建了一个新的线程,并启动了这两个线程。

七、diy一下

改成信号量机制:

import java.util.concurrent.Semaphore;

public class os1_1_1 {
    static class Q {
        String name;
        int num = 0;
        int size = 10;
        Semaphore empty = new Semaphore(size);
        Semaphore full = new Semaphore(0);
        Semaphore mutex = new Semaphore(1);
    }

    static class Producer implements Runnable {
        Q q;

        Producer(Q q) {
            this.q = q;
            this.q.name = "producer";
        }

        public void run() {
            while (true) {
                try {
                    q.empty.acquire();
                    q.mutex.acquire();
                    q.num++;
                    System.out.println("producer已生产第:" + q.num + "个产品!");
                    Thread.currentThread().sleep(100);
                    q.mutex.release();
                    q.full.release();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    static class Consumer implements Runnable {
        Q q;

        Consumer(Q q) {
            this.q = q;
            this.q.name = "consumer";
        }

        public void run() {
            while (true) {
                try {
                    q.full.acquire();
                    q.mutex.acquire();
                    System.out.println("consumer要消费第:" + q.num + "个产品!");
                    q.num--;
                    Thread.currentThread().sleep(100);
                    q.mutex.release();
                    q.empty.release();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

        public static void main(String[] args) {
            Q q = new Q();
            new Thread(new Producer(q)).start();
            new Thread(new Consumer(q)).start();
        }

}

这段代码中,我们使用了三个信号量:emptyfullmutexempty表示空缓冲区的数目,初始值为有界缓冲区的大小,即sizefull表示已用缓冲区的数目,初始值为0。mutex是一个互斥信号量,用于确保生产者和消费者线程之间的互斥执行,初始值为1。

在生产者线程中,我们首先调用q.empty.acquire()来获取信号量。如果成功获取信号量,则调用q.mutex.acquire()来获取互斥信号量。如果成功获取互斥信号量,则执行生产操作。完成生产操作后,我们调用q.mutex.release()来释放互斥信号量,并调用q.full.release()来释放消费者信号量,以便消费者线程可以执行消费操作。

在消费者线程中,我们首先调用q.full.acquire()来获取信号量。如果成功获取信号量,则调用q.mutex.acquire()来获取互斥信号量。如果成功获取互斥信号量,则执行消费操作。完成消费操作后,我们调用q.mutex.release()来释放互斥信号量,并调用q.empty.release()来释放生产者信号量,以便生产者线程可以执行生产操作。

看看效果:

操作系统实验进程同步,计算机操作系统实验,java,c语言,idea,windows

操作系统实验进程同步,计算机操作系统实验,java,c语言,idea,windows

改成c语言形式:

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

#define SIZE 10

typedef struct {
    char *name;
    int num;
    int size;
    sem_t empty;
    sem_t full;
    sem_t mutex;
} Q;

void *producer(void *arg) {
    Q *q = (Q *)arg;
    while (1) {
        sem_wait(&q->empty);
        sem_wait(&q->mutex);
        q->num++;
        printf("producer已生产第:%d个产品!\n", q->num);
        sleep(1);
        sem_post(&q->mutex);
        sem_post(&q->full);
    }
}

void *consumer(void *arg) {
    Q *q = (Q *)arg;
    while (1) {
        sem_wait(&q->full);
        sem_wait(&q->mutex);
        printf("consumer要消费第:%d个产品!\n", q->num);
        q->num--;
        sleep(1);
        sem_post(&q->mutex);
        sem_post(&q->empty);
    }
}

int main() {
    Q q = {.name = "Q", .num = 0, .size = SIZE};
    sem_init(&q.empty, 0, SIZE);
    sem_init(&q.full, 0, 0);
    sem_init(&q.mutex, 0, 1);

    pthread_t producer_thread, consumer_thread;
    pthread_create(&producer_thread, NULL, producer, &q);
    pthread_create(&consumer_thread, NULL, consumer, &q);

    pthread_join(producer_thread, NULL);
    pthread_join(consumer_thread, NULL);

    return 0;
}

这段代码中,我们定义了一个名为Q的结构体,它包含了一个名为name的字符串指针,一个名为num的整数变量,一个名为size的整数变量,以及三个信号量:emptyfullmutex

在主函数中,我们初始化了一个Q类型的变量,并使用sem_init()函数初始化了它的三个信号量。然后我们创建了两个线程:生产者线程和消费者线程,并分别调用了producer()consumer()函数。

在生产者线程中,我们首先调用sem_wait()函数来获取信号量。如果成功获取信号量,则调用sem_wait()函数来获取互斥信号量。如果成功获取互斥信号量,则执行生产操作。完成生产操作后,我们调用sem_post()函数来释放互斥信号量,并调用sem_post()函数来释放消费者信号量,以便消费者线程可以执行消费操作。

在消费者线程中,我们首先调用sem_wait()函数来获取信号量。如果成功获取信号量,则调用sem_wait()函数来获取互斥信号量。如果成功获取互斥信号量,则执行消费操作。完成消费操作后,我们调用sem_post()函数来释放互斥信号量,并调用sem_post()函数来释放生产者信号量,以便生产者线程可以执行生产操作。


总结

这篇文章中所述的实验是从网页内容中总结的。它是一个关于进程同步控制的实验,目的是让学生理解进程同步的概念和方法,以及掌握java或c语言的多线程编程技巧。实验要求学生模拟一个生产者-消费者问题,使用信号量机制来实现进程间的同步和互斥。实验设计了一个缓冲区类,一个生产者类,一个消费者类,以及一个主类来控制程序的运行。实验结果显示,程序能够正确地运行,并且没有出现死锁或数据丢失的情况。文章来源地址https://www.toymoban.com/news/detail-754583.html

到了这里,关于操作系统实验:进程同步控制的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 计算机操作系统【慕课版】习题答案(第2章进程的描述与控制)

    一:简答题 (1).什么是前趋图?试画出下面四条语句的前趋图. S1:a=x+y; S2:b=z+1; S3:c=a-b; S4:w=c+1; 答:前趋图(Precedence Graph)是一个有向无循环图,记为DAG(DirectedAcyclicGraph),用于描述进程之间执行的前后关系。 (2)什么是进程? OS中为什么要引入进程?它会产生什么样的

    2024年04月13日
    浏览(35)
  • 操作系统:4、进程管理之进程同步

    上述过程,若并发执行就会出现缓冲区数据出错 “哲学家进餐问题中会发生极端情况,所有哲学家都饿死,也就是所有进程都陷入等待状态” “生产者消费者问题”以及“哲学家进程问题”的根源问题是:彼此相互之间没有通信。 若生产者通知消费者我已经完成一件产品生

    2023年04月26日
    浏览(51)
  • 操作系统进程线程(三)—进程状态、同步互斥、锁、死锁

    原子操作的概念 原子操作就是不可中断的一个或者一系列操作。 原子操作如何实现 总线锁定 使用处理器提供的一个LOCK#信号,当一个处理器在总线上输出此信号的时候,其他处理器的请求将被阻塞住,那么该处理器可以独占内存。 缓存锁 总线锁开销比较大,因为把CPU和内

    2024年02月04日
    浏览(51)
  • 【操作系统】第2章进程同步、PV操作、死锁

    (1) 临界资源 :把 一个时间段内只允许一个进程使用的资源 称为临界资源。许多物理设备(摄像头、打印机)和许多变量、数据、内存缓冲区都属于临界资源。 对临界资源的访问必须互斥地进行 。 ① 进入区 :为了进入临界区使用临界资源,在进入区检查可否进入临界区

    2024年02月03日
    浏览(223)
  • 操作系统-进程和线程-同步、互斥、死锁

    目录 一、同步互斥  二、互斥的实现方法 2.1软件实现 2.1.1单标志法 2.1.2双标志先检查 2.1.3双标志后检查 2.1.4Petersons算法 2.2硬件实现 2.2.1 TestAndSet指令 2.2.2 Swap指令   三、信号量机制 3.1整形变量  3.2 记录型变量  3.3用信号量实现进程互斥、同步、前驱关系 3.3.1互斥  3.3.2同步

    2024年02月08日
    浏览(52)
  • 计算机操作系统和进程

    ✨个人主页:bit me👇 ✨当前专栏:Java EE初阶👇 ✨每日一语:心平能愈三千疾,心静可通万事理。 操作系统是一组做计算机资源管理的软件的统称 目前常见的操作系统有:Windows系列、Unix系列、Linux系列、OSX系列、Android系列、iOS系列、鸿蒙等 防止硬件被时空的应用程序滥用

    2024年01月23日
    浏览(61)
  • 软考:中级软件设计师:操作系统,进程管理,前趋图,进程同步互斥,PV操作,

    提示:系列被面试官问的问题,我自己当时不会,所以下来自己复盘一下,认真学习和总结,以应对未来更多的可能性 关于互联网大厂的笔试面试,都是需要细心准备的 (1)自己的科研经历, 科研内容 ,学习的相关领域知识,要熟悉熟透了 (2)自己的实习经历,做了 什

    2024年02月12日
    浏览(53)
  • 操作系统实验(进程调度)

      1.1理解有关进程控制块、进程队列的概念。   1.2掌握进程优先权调度算法和时间片轮转调度算法的处理逻辑。   2.1设计进程控制块PCB的结构,分别适用于优先权调度算法和时间片轮转调度算法。   2.2建立进程就绪队列。   2.3编制两种进程调度算法:优先权调度

    2024年02月06日
    浏览(46)
  • 操作系统-进程同步:生产者-消费者问题

    ​ 以生产者-消费者模型为基础,在Windows环境下创建一个控制台进程(或者界面进程),在该进程中创建读者写者线程模拟生产者和消费者。写者线程写入数据,然后将数据放置在一个空缓冲区中供读者线程读取。读者线程从缓冲区中获得数据,然后释放缓冲区。当写者线程

    2023年04月20日
    浏览(49)
  • 操作系统-进程调度实验报告

    1.实现四种不同及进程调度算法: 先来先服务、时间片轮转调、优先级调度以及短作业优先调度算法。 2.通过实验理解有关进程控制块,进程队列等的概念。 1.运行素材中的代码,观察其执行结果是否正确?各个调度算法的功能是否完善?如果没有,则完善。 2. 按照下表

    2024年02月06日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包