java——PV操作

PV操作通常指的是P操作和V操作,它们是信号量(Semaphore)机制中的两个基本操作,用于解决进程或线程间的同步和互斥问题。P操作(也称为wait操作或down操作)用于将信号量的值减1,如果结果为负数,则调用该操作的进程或线程会被阻塞;V操作(也称为signal操作或up操作)用于将信号量的值加1,如果有任何进程或线程因为P操作而被阻塞,则唤醒其中一个。

在Java中,我们可以使用java.util.concurrent包中的Semaphore类来实现PV操作。以下是一个简单的示例:

java 复制代码
import java.util.concurrent.Semaphore;

public class PVExample {
    // 创建一个Semaphore对象,初始值为1(表示只有一个资源)
    private static Semaphore semaphore = new Semaphore(1);

    public static void main(String[] args) {
        Thread producer = new Thread(new Producer());
        Thread consumer = new Thread(new Consumer());

        producer.start();
        consumer.start();
    }

    // 生产者线程
    static class Producer implements Runnable {
        @Override
        public void run() {
            try {
                for (int i = 0; i < 5; i++) {
                    System.out.println("Producer is producing item " + i);
                    // 模拟生产一个物品的过程
                    Thread.sleep(1000);

                    // P操作:请求资源(信号量减1)
                    semaphore.acquire();

                    // 这里可以放置生产物品后的处理逻辑

                    System.out.println("Producer has produced item " + i + " and released the resource.");

                    // 模拟生产完成后释放资源的过程(为了演示,这里直接释放)
                    // 实际上,应该在消费者消费完资源后再释放
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    // 消费者线程
    static class Consumer implements Runnable {
        @Override
        public void run() {
            try {
                for (int i = 0; i < 5; i++) {
                    // V操作:释放资源(信号量加1)
                    // 注意:这里的V操作应该放在消费资源之后,但为了演示,我们先进行V操作
                    semaphore.release();

                    // 等待获取资源(即P操作),然后消费资源
                    semaphore.acquire();

                    System.out.println("Consumer is consuming item " + i);

                    // 模拟消费一个物品的过程
                    Thread.sleep(1500);

                    System.out.println("Consumer has consumed item " + i);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

注意 :上述代码只是一个演示,实际使用中,P操作(semaphore.acquire())应该在消费或处理资源之前进行,V操作(semaphore.release())应该在消费或处理资源之后进行。同时,上述代码中的生产和消费逻辑并不严谨,因为semaphore.release()acquire()之前调用会导致信号量的值错误地增加。

正确的逻辑应该是:

  1. 生产者生产一个物品后,调用semaphore.acquire()请求资源(P操作)。
  2. 如果资源可用(信号量大于0),则生产者继续执行,并将信号量减1。
  3. 如果资源不可用(信号量等于0),则生产者被阻塞,直到消费者释放资源。
  4. 消费者消费一个物品后,调用semaphore.release()释放资源(V操作),将信号量加1。
  5. 如果有被阻塞的生产者或消费者,则唤醒其中一个。

在实际应用中,你需要根据具体场景调整上述逻辑。

相关推荐
不才不才不不才7 分钟前
Spring 源码系列(14): JDK 动态代理 vs CGLIB,以及拦截器责任链
java·开发语言·spring
mifengxing9 分钟前
计算机组成原理——存储器系统
开发语言·考研·计算机组成原理·复习笔记·计算机408
流云鹤21 分钟前
05Java学习day(5)
java·学习
用户31268748772030 分钟前
Spring 事件机制到底怎么传播的?ApplicationEvent 源码拆解
java·spring
默辨42 分钟前
Spring AI Alibaba 核心知识点
java·ai·spring ai·spring alibaba
乐观的Terry1 小时前
10、发布系统-路由管理与灰度发布
java
唐青枫1 小时前
Java WebLogic 实战指南:从 Domain、数据源到 WAR 部署和集群管理
java
Yolanda_20221 小时前
Python学习-第九部分-错误处理与异常处理
开发语言·python·学习
郝学胜-神的一滴1 小时前
Qt 高级编程 037:QSS按钮样式封神指南
开发语言·c++·qt·软件工程·用户界面
DFT计算杂谈1 小时前
SCIENTIFIC REPORTS 非 van der Waals可调二维磁性材料设计平台
开发语言·php