当前位置: 首页 > news >正文

操作系统之进程同步

1.什么是进程同步,为什么要引入进程同步?

  • 进程同步是指多个进程在执行次序上进行协调,使它们按一定的规则共享资源和相互合作。引入进程同步是为了避免并发进程因资源竞争而产生数据不一致、混乱等问题,确保系统的稳定性和正确性。

2.同步机制应该遵循的原则是什么?为什么要遵循这些原则(可以通过举例进行解释)

  • 同步机制应遵循空闲让进、忙则等待、有限等待和让权等待原则。空闲让进可提高资源利用率,如空闲文件允许多线程写入;忙则等待防数据混乱,像多线程改数据库;有限等待避“饥饿”,保证进程执行;让权等待免忙等,使系统高效运行。

3.什么是信号量,为什么引入信号量机制?

  • 信号量是一个整型变量,用于进程同步。它有两个原子操作:P操作(等待)和V操作(释放)。引入信号量机制是为了有效解决进程同步和互斥问题,通过对信号量的操作来控制进程对临界资源的访问,避免因竞争导致的数据不一致等问题。

4.给出记录型信号量wait()和signal()操作的实现代码

import java.util.LinkedList;
import java.util.Queue;

class RecordSemaphore {
    //信号量
    private int value;
    //阻塞队列
    private Queue<Thread> queue;

    public RecordSemaphore(int value) {
        this.value = value;
        this.queue = new LinkedList<>();
    }

    public synchronized void waitOp() {
        value--;
        if (value < 0) {
            try {
                queue.add(Thread.currentThread());
                // 线程在 RecordSemaphore 对象的监视器上等待
                this.wait();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }

    public synchronized void signalOp() {
        value++;
        if (value <= 0) {
            queue.poll();
            // 在 RecordSemaphore 对象的监视器上唤醒等待的线程
            this.notify();
        }
    }

    public static void main(String[] args) {
        RecordSemaphore semaphore = new RecordSemaphore(1);

        // 创建线程 1
        Thread thread1 = new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + " 尝试获取信号量");
            semaphore.waitOp();
            System.out.println(Thread.currentThread().getName() + " 已获取信号量,正在执行操作...");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " 操作完成,释放信号量");
            semaphore.signalOp();
        }, "Thread-1");

        // 创建线程 2
        Thread thread2 = new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + " 尝试获取信号量");
            semaphore.waitOp();
            System.out.println(Thread.currentThread().getName() + " 已获取信号量,正在执行操作...");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " 操作完成,释放信号量");
            semaphore.signalOp();
        }, "Thread-2");

        // 创建线程 3
        Thread thread3 = new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + " 尝试获取信号量");
            semaphore.waitOp();
            System.out.println(Thread.currentThread().getName() + " 已获取信号量,正在执行操作...");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " 操作完成,释放信号量");
            semaphore.signalOp();
        }, "Thread-3");

        // 启动线程
        thread1.start();
        thread2.start();
        thread3.start();

        // 等待线程执行完成
        try {
            thread1.join();
            thread2.join();
            thread3.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("所有线程执行完毕");
    }
}

运行结果1:

Thread-1 尝试获取信号量
Thread-1 已获取信号量,正在执行操作...
Thread-3 尝试获取信号量
Thread-2 尝试获取信号量
Thread-1 操作完成,释放信号量
Thread-3 已获取信号量,正在执行操作...
Thread-3 操作完成,释放信号量
Thread-2 已获取信号量,正在执行操作...
Thread-2 操作完成,释放信号量
所有线程执行完毕

运行结果2:

Thread-1 尝试获取信号量
Thread-1 已获取信号量,正在执行操作...
Thread-2 尝试获取信号量
Thread-3 尝试获取信号量
Thread-1 操作完成,释放信号量
Thread-2 已获取信号量,正在执行操作...
Thread-2 操作完成,释放信号量
Thread-3 已获取信号量,正在执行操作...
Thread-3 操作完成,释放信号量

运行结果3:

Thread-2 尝试获取信号量
Thread-2 已获取信号量,正在执行操作...
Thread-3 尝试获取信号量
Thread-1 尝试获取信号量
Thread-2 操作完成,释放信号量
Thread-3 已获取信号量,正在执行操作...
Thread-3 操作完成,释放信号量
Thread-1 已获取信号量,正在执行操作...
Thread-1 操作完成,释放信号量
所有线程执行完毕

5.用wait(),signal()操作尝试实现司机和售票员进程的同步(利用信号量实现前驱关系)

import java.util.LinkedList;
import java.util.Queue;

class RecordSemaphore {
    // 信号量
    private int value;
    // 阻塞队列
    private Queue<Thread> queue;

    public RecordSemaphore(int value) {
        this.value = value;
        this.queue = new LinkedList<>();
    }

    public synchronized void waitOp() {
        value--;
        if (value < 0) {
            try {
                queue.add(Thread.currentThread());
                // 线程在 RecordSemaphore 对象的监视器上等待
                this.wait();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }

    public synchronized void signalOp() {
        value++;
        if (value <= 0) {
            queue.poll();
            // 在 RecordSemaphore 对象的监视器上唤醒等待的线程
            this.notify();
        }
    }

    public static void main(String[] args) {
        // 用于控制售票员线程开始的信号量,初始值为 1 表示可以开始
        RecordSemaphore conductorSemaphore = new RecordSemaphore(1);
        // 用于控制司机线程开始的信号量,初始值为 0 表示需要等待
        RecordSemaphore driverSemaphore = new RecordSemaphore(0);

        // 创建售票员线程
        Thread conductor = new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + " 尝试获取信号量");
            conductorSemaphore.waitOp();
            System.out.println(Thread.currentThread().getName() + " 已获取信号量,正在执行操作...");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " 操作完成,释放信号量");
            conductorSemaphore.signalOp();
            // 售票员操作完成后,释放司机线程的信号量
            driverSemaphore.signalOp();
        }, "售票员");

        // 创建司机线程
        Thread driver = new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + " 等待售票员完成操作...");
            // 等待售票员线程释放信号量
            driverSemaphore.waitOp();
            System.out.println(Thread.currentThread().getName() + " 尝试获取信号量");
            conductorSemaphore.waitOp();
            System.out.println(Thread.currentThread().getName() + " 已获取信号量,正在执行操作...");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " 操作完成,释放信号量");
            conductorSemaphore.signalOp();
        }, "司机");

        // 启动线程
        conductor.start();
        driver.start();

        // 等待线程执行完成
        try {
            conductor.join();
            driver.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("所有线程执行完毕");
    }
}    

测试结果如下:

售票员 尝试获取信号量
司机 等待售票员完成操作...
售票员 已获取信号量,正在执行操作...
售票员 操作完成,释放信号量
司机 尝试获取信号量
司机 已获取信号量,正在执行操作...
司机 操作完成,释放信号量
所有线程执行完毕

相关文章:

  • python的flask框架连接数据库
  • 区块链从专家到小白
  • GAS:车载体验的智能革新力量
  • Rag实现流程
  • 软件界面设计:打造用户喜爱的交互体验
  • 新版雷电模拟器过应用检测技术详解
  • leetcode 264. Ugly Number II
  • ReactNative 使用腾讯的MMKV持久化存储
  • 深入浅出:信号灯与系统V信号灯的实现与应用
  • 区块链点燃游戏行业新未来——技术变革与实践指南
  • 【Linux网络与网络编程】08.传输层协议 UDP
  • 互联网三高-数据库高并发之分库分表
  • PostgreSQL 的统计信息
  • 0x02.Redis 集群的实现原理是什么?
  • 80_Pandas如何使用NumPy的函数等(pd.np)
  • 【图像生成之21】融合了Transformer与Diffusion,Meta新作Transfusion实现图像与语言大一统
  • Hadoop文件操作指南:深入解析文件操作
  • 北洋底标印记纪年
  • TDengine 可靠性保障:数据持久化与容灾备份(二)
  • ZYNQ笔记(六):自定义IP核-LED呼吸灯
  • 中国b2b网站有哪些/注册域名后如何建立网站
  • 民兵信息化网站建设/个人小白如何做手游代理
  • 江阴网站推广/电商平台运营方案
  • 免费新建网站/网站搭建策略与方法
  • 重庆建设网站/接外包网站
  • 营销型网站建设明细报/搜索引擎优化举例说明