转---秒杀多线程第十二篇 多线程同步内功心法——PV操作上 (续)
PV操作的核心就是 PV操作可以同时起到同步与互斥的作用。
1.同步就是通过P操作获取信号量,V操作释放信号量来进行。
2.互斥其实就是,同时操作P操作,结束后进行V操作即可做到。
Java上实现PV操作可以通过Semaphore来实现。
package com.multithread.pvoperator; import java.util.concurrent.Semaphore; /*
P(S): ①将信号量S的值减1,即S=S-1; ②如果S>=0,则该进程继续执行;否则该进程置为等待状态。 V(S): ①将信号量S的值加1,即S=S+1; ②该进程继续执行;如果该信号的等待队列中有等待进程就唤醒一等待进程。
*
* */
public class PVObject { private Semaphore mSemaphore =null;
private int Max_size = 0xff;
private String name = null;
public PVObject(int size,String name)
{
if(size>0)
{
Max_size = size;
mSemaphore = new Semaphore(size);
}
this.name = name;
} public PVObject(String name)
{
Max_size = 1;
mSemaphore = new Semaphore(1);
this.name = name;
} public void Init(int status)
{
if(status<0 || status>Max_size)
{
System.out.println("[PVObject][Init]"+name+" wrong,status:"+status);
return;
} if(status == Max_size)
{
return;
} try {
mSemaphore.release(Max_size);
mSemaphore.acquire(Max_size-status);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} public void P()
{
try {
//
mSemaphore.acquire();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} public void V()
{
mSemaphore.release();
}
}
分水果问题Java是实现:
package com.multithread.pvoperator; import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors; public class Fruit {
/*
* 下面先考虑同步情况即所有“等待”情况:
第一.爸爸要等待盘子为空。
第二.儿子要等待盘中水果是桔子。
第三.女儿要等待盘中水果是苹果。
接下来来考虑要互斥处理的资源,看起来盘子好像是要作互斥处理的,
但由于题目中的爸爸、儿子、女儿均只有一个,并且他们访问盘子的条件都不一样,
所以他们根本不会同时去访问盘子,因此盘子也就不用作互斥处理了
*
* */
public PVObject mEmptyDash = new PVObject("emptyDash");//
public PVObject mApple = new PVObject("apple"); //
public PVObject mOranger = new PVObject("oranger"); //
public boolean mDadEnd = false;
public CountDownLatch mLatchDown = new CountDownLatch(3);
public CountDownLatch mLatchStart = new CountDownLatch(3);
public Queue<Integer> mQueue = new LinkedList<Integer>();
public void Start()
{
mEmptyDash.Init(1);
mApple.Init(0);
mOranger.Init(0);
mQueue.clear();
Executor mEcecutor = Executors.newFixedThreadPool(5);
mEcecutor.execute(new Dad(this));
mEcecutor.execute(new Daughter(this));
mEcecutor.execute(new Son(this)); try {
mLatchStart.await();
System.out.println("all thread start"); mLatchDown.await();
System.out.println("all thread down");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} public class Dad extends Thread{ public Fruit mFruit = null;
boolean flag = true;
public int MAX_FRUIT_COUNT = 20;
public int index = 0;
public Dad(Fruit f)
{
mFruit = f;
}
@Override
public void run() {
mLatchStart.countDown();
while(flag)
{
mFruit.mEmptyDash.P(); index++;
if(index >=MAX_FRUIT_COUNT)
{
flag = false;
} mQueue.offer(index); if((int)(Math.random()*2) == 1)
{
System.out.println("dad put apple"+index+" to dash");
//apply
mFruit.mApple.V();
}
else
{
//oranger
System.out.println("dad put oranger"+index+" to dash");
mFruit.mOranger.V();
}
}
mFruit.mDadEnd = true;
System.out.println("dad thread is end");
mLatchDown.countDown();
}
} public class Daughter extends Thread{ public Fruit mFruit = null;
boolean flag = true;
public Daughter(Fruit f)
{
mFruit = f;
}
@Override
public void run() {
mLatchStart.countDown();
while(flag)
{
mFruit.mOranger.P();
if(mQueue.size()>0)
{
System.out.println("Daughter get oranger"+mQueue.poll()+" from dash");
mFruit.mEmptyDash.V();
}
else
{
System.out.println("Daughter get oranger from dash,but dash is empty");
} if(mFruit.mDadEnd == true)
{
flag = false;
}
}
System.out.println("Daughter thread is end");
//notify son down,for this dad is down.
mApple.V();
mLatchDown.countDown();
}
} public class Son extends Thread{ public Fruit mFruit = null;
boolean flag = true;
public Son(Fruit f)
{
mFruit = f;
}
@Override
public void run() {
mLatchStart.countDown();
while(flag)
{
mFruit.mApple.P();
if(mQueue.size()>0)
{
System.out.println("Son get apple"+mQueue.poll()+" from dash");
mFruit.mEmptyDash.V();
}
else
{
System.out.println("Son get apple from dash,but dash is empty");
} if(mFruit.mDadEnd == true)
{
flag = false;
}
}
System.out.println("Son thread is end");
mOranger.V();
mLatchDown.countDown();
}
}
}
安全岛问题:
package com.multithread.pvoperator; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors; public class SafeIsland { public PVObject NT = new PVObject("NLoad");
public PVObject TN = new PVObject("TLoad");
public PVObject K = new PVObject("K");
public PVObject L = new PVObject("L");
public static final int MAX_NANKAI_CAR_COUNT = 2;
public static final int MAX_TIANJING_CAR_COUNT = 3;
public CountDownLatch mLatchDown = new CountDownLatch(MAX_NANKAI_CAR_COUNT+MAX_TIANJING_CAR_COUNT); public class NanKaiCar extends Thread{
String name = null;
public NanKaiCar(String name)
{
this.name = name;
}
@Override
public void run() {
System.out.println("[NanKaiCar]"+name+" Thread start");
try {
Thread.sleep((long) (Math.random()*100));
NT.P();
System.out.println("[NanKaiCar]"+name+" enter crossing N");
K.P();
System.out.println("[NanKaiCar]"+name+" walk to M:N->M");
Thread.sleep((long) (Math.random()*1000));
System.out.println("[NanKaiCar]"+name+" start walk to T");
K.V();
L.P();
System.out.println("[NanKaiCar]"+name+" walk to T:M->T");
L.V();
NT.V();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mLatchDown.countDown();
System.out.println("[NanKaiCar]"+name+" walk down");
} } public class TianJingCar extends Thread{
String name = null;
public TianJingCar(String name)
{
this.name = name;
}
@Override
public void run() { try {
System.out.println("[TianJingCar]"+name+" Thread start");
Thread.sleep((long) (Math.random()*100));
TN.P();
System.out.println("[TianJingCar]"+name+" enter crossing T");
L.P();
System.out.println("[TianJingCar]"+name+" walk to M:T->M");
Thread.sleep((long) (Math.random()*1000));
System.out.println("[TianJingCar]"+name+" start walk to N");
L.V();
K.P();
System.out.println("[TianJingCar]"+name+" walk to T:M->N");
K.V();
TN.V();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mLatchDown.countDown();
System.out.println("[TianJingCar]"+name+" walk down");
} } public void start()
{
NT.Init(1);
TN.Init(1);
K.Init(1);
L.Init(1);
Executor mEcecutor = Executors.newFixedThreadPool(MAX_TIANJING_CAR_COUNT+MAX_NANKAI_CAR_COUNT+1);
for(int i =1;i<=MAX_NANKAI_CAR_COUNT;i++)
{
mEcecutor.execute(new NanKaiCar("carN"+i));
}
for(int j=1;j<=MAX_TIANJING_CAR_COUNT;j++)
{
mEcecutor.execute(new TianJingCar("carT"+j));
}
try {
mLatchDown.await();
System.out.println("all car has pass road");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} }
生产消费者问题伪代码:
package com.multithread.pvoperator;
public class Prosumer {
//PV 分析 生产者,消费者问题
/*同步: 生产者:缓冲区有空间,就放入数据 P(EmptyS) 只有空和不空,信号量为1
* 消费者:缓冲区有数据,就读取数据,并移走数据 P(NotEmptyS),信号量为缓冲区大小
*互斥: 生产者 写入数据,和消费者移走数据互斥 P(OperatorS),用来互斥,信号量为1
* 消费者异步读取移动数据,互斥
* */
public class Productor extends Thread{
@Override
public void run() {
while(true)
{
P(EmptyS);
P(OperatorS);
//operator data
V(OperatorS);
V(NotEmptyS);//通知不为空
}
}
}
public class Consumer extends Thread{
@Override
public void run() {
P(NotEmptyS);
P(OperatorS);
//operator data
V(OperatorS);
V((EmptyS);
}
}
}
package com.multithread.pvoperator;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
public class Fruit {
/*
* 下面先考虑同步情况即所有“等待”情况:
第一.爸爸要等待盘子为空。
第二.儿子要等待盘中水果是桔子。
第三.女儿要等待盘中水果是苹果。
接下来来考虑要互斥处理的资源,看起来盘子好像是要作互斥处理的,
但由于题目中的爸爸、儿子、女儿均只有一个,并且他们访问盘子的条件都不一样,
所以他们根本不会同时去访问盘子,因此盘子也就不用作互斥处理了
*
* */
public PVObject mEmptyDash = new PVObject("emptyDash");//1
public PVObject mApple = new PVObject("apple"); //0
public PVObject mOranger = new PVObject("oranger"); //0
public boolean mDadEnd = false;
public CountDownLatch mLatchDown = new CountDownLatch(3);
public CountDownLatch mLatchStart = new CountDownLatch(3);
public Queue<Integer> mQueue = new LinkedList<Integer>();
public void Start()
{
mEmptyDash.Init(1);
mApple.Init(0);
mOranger.Init(0);
mQueue.clear();
Executor mEcecutor = Executors.newFixedThreadPool(5);
mEcecutor.execute(new Dad(this));
mEcecutor.execute(new Daughter(this));
mEcecutor.execute(new Son(this));
try {
mLatchStart.await();
System.out.println("all thread start");
mLatchDown.await();
System.out.println("all thread down");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public class Dad extends Thread{
public Fruit mFruit = null;
boolean flag = true;
public int MAX_FRUIT_COUNT = 20;
public int index = 0;
public Dad(Fruit f)
{
mFruit = f;
}
@Override
public void run() {
mLatchStart.countDown();
while(flag)
{
mFruit.mEmptyDash.P();
index++;
if(index >=MAX_FRUIT_COUNT)
{
flag = false;
}
mQueue.offer(index);
if((int)(Math.random()*2) == 1)
{
System.out.println("dad put apple"+index+" to dash");
//apply
mFruit.mApple.V();
}
else
{
//oranger
System.out.println("dad put oranger"+index+" to dash");
mFruit.mOranger.V();
}
}
mFruit.mDadEnd = true;
System.out.println("dad thread is end");
mLatchDown.countDown();
}
}
public class Daughter extends Thread{
public Fruit mFruit = null;
boolean flag = true;
public Daughter(Fruit f)
{
mFruit = f;
}
@Override
public void run() {
mLatchStart.countDown();
while(flag)
{
mFruit.mOranger.P();
if(mQueue.size()>0)
{
System.out.println("Daughter get oranger"+mQueue.poll()+" from dash");
mFruit.mEmptyDash.V();
}
else
{
System.out.println("Daughter get oranger from dash,but dash is empty");
}
if(mFruit.mDadEnd == true)
{
flag = false;
}
}
System.out.println("Daughter thread is end");
//notify son down,for this dad is down.
mApple.V();
mLatchDown.countDown();
}
}
public class Son extends Thread{
public Fruit mFruit = null;
boolean flag = true;
public Son(Fruit f)
{
mFruit = f;
}
@Override
public void run() {
mLatchStart.countDown();
while(flag)
{
mFruit.mApple.P();
if(mQueue.size()>0)
{
System.out.println("Son get apple"+mQueue.poll()+" from dash");
mFruit.mEmptyDash.V();
}
else
{
System.out.println("Son get apple from dash,but dash is empty");
}
if(mFruit.mDadEnd == true)
{
flag = false;
}
}
System.out.println("Son thread is end");
mOranger.V();
mLatchDown.countDown();
}
}
}
转---秒杀多线程第十二篇 多线程同步内功心法——PV操作上 (续)的更多相关文章
- 多线程同步内功心法——PV操作上(未完待续。。。)
阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇一个经典的多线程同步问题> <秒杀多线程第五篇经典线程同步关键段CS> <秒杀多线程第六篇经典线程同步事件Event& ...
- 多线程面试题系列(12):多线程同步内功心法——PV操作上
上面的文章讲解了在Windows系统下实现多线程同步互斥的方法,为了提高在实际问题中分析和思考多个线程之间同步互斥问题的能力,接下来将讲解PV操作,这也是操作系统中的重点和难点.本文将会先简要介绍下P ...
- C++第五十二篇 -- 多线程之消息传递
主线程向子线程发送消息 参考链接:https://www.cnblogs.com/ranjiewen/p/5729539.html 1. 创建线程语句 HANDLE hThread; DWORD dw ...
- “全栈2019”Java多线程第二十二章:饥饿线程(Starvation)详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- “全栈2019”Java多线程第十二章:后台线程setDaemon()方法详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- “全栈2019”Java多线程第十六章:同步synchronized关键字详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- 解剖SQLSERVER 第十二篇 OrcaMDF 行压缩支持(译)
解剖SQLSERVER 第十二篇 OrcaMDF 行压缩支持(译) http://improve.dk/orcamdf-row-compression-support/ 在这两个月的断断续续的开发 ...
- 第十二篇 SQL Server代理多服务器管理
本篇文章是SQL Server代理系列的第十二篇,详细内容请参考原文 在这一系列的上一篇,我们查看了维护计划,一个维护计划可能会创建多个作业,多个计划.你还简单地看了SSIS子系统,并查看了维护计划作 ...
- 第十二篇 Integration Services:高级日志记录
本篇文章是Integration Services系列的第十二篇,详细内容请参考原文. 简介在前一篇文章我们配置了SSIS内置日志记录,演示了简单和高级日志配置,保存并查看日志配置,生成自定义日志消息 ...
随机推荐
- 20155331 《Java程序设计》实验一(Java开发环境的熟悉)实验报告
20155331 <Java程序设计>实验一(Java开发环境的熟悉)实验报告 一.实验内容及步骤 使用JDK编译.运行简单的java程序 实验目的与要求: 使用JDK和IDE编译.运行简 ...
- c++ 结构指针和双向链表
结构指针 为结构指针动态分配内存 结构中的结构 双向链表 结构指针 struct mytime { //char name[256]; int hour;//时 int min; //分 i ...
- 【LG3242】 [HNOI2015]接水果
题面 洛谷 题解 20pts 对于\(n,P,Q\leq 3000\),暴力判断每条路径的包含关系然后排序\(kth\)即可,复杂度\(O(PQ\log P)\) 另30pts 原树为一条链. 发现对 ...
- 【LG1445】樱花
[LG1445]樱花 题面 洛谷 题解 \[ \frac 1x+\frac 1y=\frac 1{n!}\\ \frac{x+y}{xy}=\frac 1{n!}\\ n!(x+y)=xy\\ xy- ...
- 【LG5022】[NOIP2018]旅行
[LG5022][NOIP2018]旅行 题面 洛谷 题解 首先考虑一棵树的部分分怎么打 直接从根节点开始\(dfs\),依次选择编号最小的儿子即可 而此题是一个基环树 怎么办呢? 可以断掉环上的一条 ...
- centos7下python3与python2共存并且开启py3虚拟环境
因为下载视频需要用到python3环境,今天在我的win上安装下载工具死活安装不上去,在大盘鸡上一下就安装成功了...可能在win上不兼容吧...无奈只能在大盘鸡上进行折腾了,顺便几个笔记 由于大盘鸡 ...
- activeX 打包
原文 http://www.docin.com/p-409284488.html CAB打包文档说明 文档目的 本文档的目的在于说明将ocx和dll以及相关的文件打包成一个CAB包,以便在网页下调用o ...
- 《Cocos2d-x游戏开发实战精解》学习笔记4--实战一个简单的钢琴
上一节学习了使用Cocos2d-x播放音乐的方法,但是那种方法一般只适合于播放较大的音乐,而一般比较短小的音乐(如游戏中的打斗.按键音效等)则要通过playEffect来播放.本节使用该方法以及之前学 ...
- 市场营销的4c原则
市场营销的4c原则随着市场竞争日趋激烈,媒介传播速度越来越快,4Ps理论越来越受到挑战.到80年代,美国劳特朋针对4P存在的问题提出了4Cs营销理论: 4C分别指代Customer(顾客).Cost( ...
- 什么是Meta标签? 哪些Meta标签对搜索引擎SEO优化有作用?
什么是Meta标签? Meta标签给搜索引擎提供了许多关于网页的信息,这些信息都是隐含信息,意味着对于网页自身的访问者是不可见的. 你可以在网页的 <head>元素中发现<meta& ...