Art of Multiprocessor Programming 答案 ch8

本文通过具体实现探讨了多种并发控制机制,包括读写锁、优先级队列、浴室问题、房间分配及倒计时门闩等经典场景。展示了如何使用条件变量、锁及其他同步工具解决并发编程中的挑战。

93.

package p93;

import java.util.concurrent.locks.Lock;

public class SimpleRWLock
{
	private class ReadLock implements Lock
	{
		public void lock()
		{
			try
			{
				synchronized(lockObj)
				{
					while(writer)
					{
						lockObj.wait();
					}
				
					readers ++;
				}
			}catch(Exception e)
			{
				e.printStackTrace();
			}
		}
		 
		public void unlock()
		{
			synchronized(lockObj)
			{
				if(readers <= 0)
				{
					lockObj.notifyAll();
				}
			}
		}
		
		public void lockInterruptibly() throws java.lang.InterruptedException
		{
			throw new InterruptedException();
		}
		  
		public boolean tryLock()
		{
			return false;
		}
		  
		public boolean tryLock(long arg0, java.util.concurrent.TimeUnit arg1) throws java.lang.InterruptedException
		{
			throw new InterruptedException();
		}
		  
		public java.util.concurrent.locks.Condition newCondition()
		{
			return null;
		}
	}
	
	private class WriteLock implements Lock
	{
		public void lock()
		{
			try
			{
				synchronized(lockObj)
				{
					while(readers > 0 || writer)
					{
						lockObj.wait();
					}
					
					writer =  true;
				}
			}catch(Exception e)
			{
				e.printStackTrace();
			}
		}
		 
		public void unlock()
		{
			synchronized(lockObj)
			{
				writer = false;
				lockObj.notifyAll();
			}
		}
		
		public void lockInterruptibly() throws java.lang.InterruptedException
		{
			throw new InterruptedException();
		}
		  
		public boolean tryLock()
		{
			return false;
		}
		  
		public boolean tryLock(long arg0, java.util.concurrent.TimeUnit arg1) throws java.lang.InterruptedException
		{
			throw new InterruptedException();
		}
		  
		public java.util.concurrent.locks.Condition newCondition()
		{
			return null;
		}		
	}
	
	private int readers;
	private boolean writer;
	private Object lockObj;
	private ReadLock readLock;
	private WriteLock writeLock;
	
	public SimpleRWLock()
	{
		lockObj = new Object();
		readLock = new ReadLock();
		writeLock = new WriteLock();
	}
	
	public Lock readLock()
	{
		return readLock;
	}
	
	public Lock writeLock()
	{
		return writeLock;
	}
	
	public static void main(String[] args)
	{
		SimpleRWLock lock = new SimpleRWLock();
		
		lock.readLock().lock();
		lock.readLock().unlock();
		lock.writeLock().lock();
		lock.writeLock().unlock();
	}
}


94.

会有  readlock.lock() --> readwait > readrelease --> writelock.lock() --> write = true --> waiting for readwait == readrelease ==> deadlock

其他的线程会有 write == true ==> block


95. 不一定全部会返回,因为可能在别人的cond上死锁,boss notify自己的锁线程感应不到。比如下面的case:

package p95;


public class Prefer 
{
	private int balance;
	private int preferRequests;
	
	public static final int PREFER = 1;
	public static final int NORMAL = 2;
	
	public Prefer()
	{
		balance = 0;
		preferRequests = 0;
	}
	
	public Prefer(int initial)
	{
		this();
		balance = initial;
	}
	
	private void deposit_nolock(int k)
	{
		balance += k;
	}
	public synchronized void deposit(int k)
	{
		deposit_nolock(k);
		this.notifyAll();
	}
	
	public synchronized void withdraw(int k, int style)
	{
		try
		{
			switch(style)
			{
			case NORMAL:
				while(preferRequests > 0 || balance < k)
				{
					this.wait();
				}
				balance -= k;
				break;
			case PREFER:
				preferRequests ++;
				while(balance < k)
				{
					this.wait();
				}
				balance -= k;
				preferRequests --;
				this.notifyAll();
				break;
			default:
				throw new InterruptedException();
			}
		}catch(InterruptedException e)
		{
			this.notifyAll();
		}
	}
	
	public synchronized void transfer(Prefer other, int k)
	{
		other.withdraw(k, NORMAL);
		deposit_nolock(k);
	}
	
} 

package p95;

public class TestThread extends Thread
{
	private Prefer myAccount;
	private Prefer otherAccount;
	public final int WITHDRAW = 200;
	public final int BOSS = 1000;
	
	public TestThread(Prefer me, Prefer other)
	{
		this.myAccount = me;
		this.otherAccount = other;
	}
	
	public void run()
	{
		System.out.println("To transfer ");
		myAccount.transfer(otherAccount, WITHDRAW);
		System.out.println("End of transfer ");
	}	
	
	public void boss()
	{
		myAccount.deposit(BOSS);
	}
	
	public static void main(String[] args)
	{
		Prefer[] accounts = new Prefer[2];
		for(int i = 0; i < accounts.length; i ++)
		{
			accounts[i] = new Prefer(0);
		}
		
		TestThread tester1 = new TestThread(accounts[0], accounts[1]);
		TestThread tester2 = new TestThread(accounts[1], accounts[0]);
		
		tester1.start();
		tester2.start();
		
		try
		{
			Thread.sleep(1000);
		}catch(Exception e)
		{
			e.printStackTrace();
		}
		System.out.println("After sleep ");
		
		tester1.boss();
		tester2.boss();
	}
}

96.

package p96;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Bathroom_1
{
	private Lock lock;
	private Condition maleCond;
	private Condition femaleCond;
	private int maleAcq;
	private int maleRel;
	private int femaleAcq;
	private int femaleRel;
	private int maleWait;
	private int femaleWait;
	
	public static final int MALE = 1;
	public static final int FEMALE = 2;
	
	public Bathroom_1()
	{
		lock = new ReentrantLock();
		maleCond = lock.newCondition();
		femaleCond = lock.newCondition();
	}
	
	public void maleEnter()
	{
		lock.lock();
		
		try
		{
			maleWait ++;
			while((femaleWait != femaleAcq && maleAcq != maleRel) 
					|| (femaleAcq != femaleRel))
			{
				maleCond.await();
			}
			
			maleAcq ++;
		}catch(Exception e)
		{
			e.printStackTrace();
			maleWait --;
			maleCond.signalAll();
			femaleCond.signalAll();
		}finally
		{
			lock.unlock();
		}
	}
	
	public void maleExit()
	{
		lock.lock();
		
		maleRel ++;
		if(maleRel == maleAcq)
		{
			femaleCond.signalAll();
		}
		
		lock.unlock();
	}
	
	public void femaleEnter()
	{
		lock.lock();
		
		try
		{
			femaleWait ++;
			while((maleWait != maleAcq && femaleAcq != femaleRel) 
					|| (maleAcq != maleRel))
			{
				femaleCond.await();
			}
			femaleAcq ++;
		}catch(Exception e)
		{
			e.printStackTrace();
			femaleWait --;
			maleCond.signalAll();
			femaleCond.signalAll();
		}finally
		{
			lock.unlock();
		}
	}
	
	public void femaleExit()
	{
		lock.lock();
		
		femaleRel ++;
		if(femaleRel == femaleAcq)
		{
			maleCond.signalAll();
		}
		
		lock.unlock();
	}
}

97.

package p97;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Rooms
{
	public interface Handler
	{
		void onEmpty();
	}
	
	private Lock lock;
	private Condition[] conds;
	private int waiting[];
	private int acquire[];
	private int release[];
	private Handler[] handlers;
	private final int m;
	private int currRoom;
	
	public Rooms(int m)
	{
		this.m = m;
		lock = new ReentrantLock();
		conds = new Condition[m + 1];
		for(int i = 0; i < conds.length; i ++)
		{
			conds[i] = lock.newCondition();
		}
		waiting = new int[m + 1];
		acquire = new int[m + 1];
		release = new int[m + 1];
		handlers = new Handler[m + 1];
		currRoom = -1;
	}
	
	private boolean toWait(int index)
	{
		if(currRoom == -1)
		{
			return false;
		}
		if(currRoom != index)
		{
			return true;
		}
		for(int i = 1; i <= m; i ++)
		{
			int other = (i + index) % (m + 1);
			if(waiting[other] != acquire[other])
			{
				return true;
			}
		}
		return false;
	}
	
	public void enter(int i)
	{
		if(i < 0 || i > m)
		{
			return;
		}
		
		lock.lock();
		
		try
		{
			waiting[i] ++;
			
			while(toWait(i))
			{
				conds[i].await();
			}
			
			acquire[i] ++;
			currRoom = i;
		}catch(Exception e)
		{
			e.printStackTrace();
		}finally
		{
			lock.unlock();
		}
	}
	
	private int notifyWho()
	{
		for(int i = 1; i <= m; i ++)
		{
			int other = (i + currRoom) % (m + 1);
			if(waiting[other] != acquire[other])
			{
				return other;
			}
		}
		
		return -1;
	}
	
	public boolean exit()
	{
		lock.lock();
		
		release[currRoom] ++;
		if(release[currRoom] == acquire[currRoom])
		{
			if(handlers[currRoom] != null)
			{
				handlers[currRoom].onEmpty();
			}
			
			int other = notifyWho();
			if(other >= 0)
			{
				conds[other].signalAll();
			}
			currRoom = -1;
		}
		
		lock.unlock();
		return true;
	}
	
	public void setExitHandler(int i, Rooms.Handler handler)
	{
		if(i < 0 || i > m)
		{
			return;
		}
		
		lock.lock();
		handlers[i] = handler;
		lock.unlock();
	}
}


98.

package p98;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;


public class CountDownLatch 
{
	private Lock lock;
	private Condition cond;
	private int m;
	
	public CountDownLatch(int m)
	{
		this.m = m;
		lock = new ReentrantLock();
		cond = lock.newCondition();
	}
	
	public void countDown()
	{
		lock.lock();
		m --;
		if(m <= 0)
		{
			cond.signalAll();
		}
		lock.unlock();
	}
	
	public void await()
	{
		lock.lock();
		
		try
		{
			while(m > 0)
			{
				cond.await();
			}
		}catch(Exception e)
		{
			e.printStackTrace();
		}finally
		{
			lock.unlock();
		}
	}
	
	/*
	 * Lock is not necessary as:
	 * 1.	set m at anytime can get matching history
	 * 2.	User should take care of reset since I don't want to block reset() method
	 */
	public void reset(int m)
	{
		lock.lock();
		this.m = m;
		lock.unlock();
	}
}


源码下载地址: https://pan.quark.cn/s/a4b39357ea24 在信息技术领域中,UML(统一建模语言)被视为一种通用的建模手段,其主要功能在于对软件开发过程中的各种概念进行可视化呈现,从而使得复杂系统结构的理解、设计及沟通变得更加便捷。以"个人通讯录系统uml图"为例,本案例将详细阐述如何运用UML图,尤其是ER图(实体关系图),来构建一个个人通讯录系统的数据模型。 首先,让我们对UML图的基本分类有所认识。UML图涵盖了多种类型,包括但不限于用例图、类图、序列图、协作图、状态图、活动图、组件图以及部署图。就本项目的实际情况而言,用例图(用于描述用户与系统的互动过程)、类图(界定对象与类之间的关联性)以及ER图(揭示数据库中实体及其相互联系)将是最为关键的应用。 用例图通过展现系统的主要参与者(users)及其能够执行的操作(use cases),并明确这些操作之间的相互联系,来描绘系统的核心功能。在个人通讯录系统的应用场景中,参与者可能涵盖普通用户,而用例则可能涉及添加联系人、搜索联系人、修改联系人信息以及删除联系人等操作。 类图则着重于展示类的组织结构,其中包括类名、属性和方法。在个人通讯录系统的构建过程中,可以设立一个"Contact"类来代表单个联系人,该类将包含诸如姓名、电话、邮箱等属性。同时,还可以设计一个"AddressBook"类来负责管理多个联系人,此类将集成添加、删除和查找联系人的功能。 ER图作为数据库设计的核心工具,主要用于表达实体、属性以及实体间的关联关系。在个人通讯录系统的设计中,实体可能包含"User"(用户)和"Contact"(联系人)。"User"实体可能具备用户名、密码等属性,而"Contact"实...
已经博主授权,源码转载自 https://pan.quark.cn/s/a4b39357ea24 标题中所提及的“PB9转换utf-8例子”具体描述了在PowerBuilder 9(PB9)环境中,将数据从非UTF-8编码格式转变为UTF-8编码格式的一种具体方案。鉴于PB9本身并不具备直接进行此类编码转换的功能,开发人员通常需要借助外部库或者特定的编程策略来达成这一功能。在此例中,采用了ADODB.Stream对象,该对象是Microsoft ActiveX Data Objects (ADO)框架内的一部分,它能够支持多种类型流数据的处理,其中包括文本数据的编码变更。 描述部分指出,由于PowerBuilder 9及其以下版本未内建直接的字符编码转换机制,因此需要借助ADODB.Stream。这个对象提供了一种途径,通过读取原始编码的文本,并将其写入到新的以UTF-8编码的流中,从而实现转换。这一过程一般包括启动一个流对象,设定其编码类型,读取原始数据,然后以目标编码(此处为UTF-8)写入到新流,最终保存结果。 标签“pb9 utf-8”清晰地表明了讨论的主题是关于PowerBuilder 9与UTF-8编码相关的问题。UTF-8是一种应用广泛的Unicode字符编码,能够表示Unicode字符集中几乎所有字符,涵盖了全球多种语言文字。 在压缩包内的文件清单中,包含了四个与PowerBuilder相关的文件(utf-8.pbl、utf-8.pbt、utf-8.pbw)以及三个文本文件(aaa.txt、www.txt、bbb.txt)。这四个PB文件或许包含了示例代码、项目配置和工作区信息,用于展示如何运用ADODB.Stream进行编码转换。而aaa.txt、www...
内容概要:本文提出了一种基于粒子群算法(PSO)融合动态窗口法(DWA)的无人机三维动态避障路径规划方法,旨在解决无人机在复杂、动态环境中安全高效飞行的路径规划难题。该方法通过Matlab代码实现,有效结合了PSO算法的全局寻优能力与DWA算法的局部实时避障优势,能够在存在移动障碍物的三维空间中规划出平滑、安全且优化的飞行路径。研究内容涵盖算法原理设计、融合机制构建、仿真环境搭建、路径规划性能测试与分析,充分验证了该融合策略在应对动态障碍物、提升避障实时性与路径质量方面的优越性。; 适合人群:具备一定编程基础和无人系统相关知识的科研人员,特别适用于从事无人机自主导航、智能优化算法、机器人路径规划等领域研究的研究生、高校教师及工程技术人员。; 使用场景及目标:①应用于城市、森林、灾害救援等复杂动态环境下的无人机自主飞行与实时避障;②为智能交通、物流配送、电力巡检、安防监控等领域的移动机器人路径规划提供先进的算法参考和技术解决方案;③作为智能优化算法与机器人技术融合教学与科研实验的重要案例。; 阅读建议:建议读者结合提供的Matlab代码进行仿真实验,深入理解PSO与DWA的融合逻辑、关键参数的敏感性分析及避障效果的评价指标,鼓励在掌握核心思想的基础上进行算法改进与创新应用。
下载代码方式:https://pan.quark.cn/s/083848db8d95 I2C 数据交互过程 I2C 数据交互过程是指经由 I2C 总线完成的数据通信环节,此环节涵盖了主设备与从设备间的数据互换。在 I2C 数据交互过程中,主设备承担着启动并管理整个通信环节的任务,而从设备则负责对主设备的指令做出响应并进行数据传输。 在 I2C 数据交互过程中,主设备需首先发出起始信号(Start),随后传输从设备的地址信息,其中最低位为读写控制位(0 代表写入,1 代表读取),高位则为从设备地址编码。随后,从设备发出应答信号(Ack),表明已准确接收地址信息。 在数据读取或写入环节中,主设备能够对从设备执行读取或写入操作。若为读取操作,主设备将发送读取指令和地址信息,从设备则反馈所读取的数据。而在写入操作时,主设备会发送写入指令及需写入的数据,从设备将其存储到指定地址。 在整个 I2C 数据交互过程中,必须遵循 I2C 总线的时序规范,例如,在时钟线(SCL)维持高电平期间,数据线(SDA)不得发生电平变动,以免被误识别为起始或终止信号。 在电可擦除只读存储器(EEPROM)设备中,I2C 数据交互过程可用于执行对 EEPROM 的读取和写入操作。EEPROM 是一种可电擦除的只读存储装置,用于保存产品的固定参数。EEPROM 允许精确访问每个字节,支持单字节写入、分页写入、随机单字节读取、当前指针单字节读取等多种数据交互方式。 在 EEPROM 设备上,能够运用包括单字节写入、分页写入、随机单字节读取、当前指针单字节读取在内的多种数据交互模式。单字节写入是指将一个字节的数据记录到 EEPROM 中,分页写入是指将一页的数据记录到 EEPROM 中。随机单字节...
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值