其他分享
首页 > 其他分享> > BUAA_OO_2022_Unit_2_Summary

BUAA_OO_2022_Unit_2_Summary

作者:互联网

零、目录

一、程序设计构架

第一次作业
第二次作业
第三次作业
协作图

附:度量分析条目解释

二、调度器设计

三、同步块与锁分析

本单元代码中的所有用到共享对象的部分,我都选择了使用 synchronized 加锁。主要用途如下:

// Controller.java
// requests为类内属性
public synchronized void addRequest(PersonRequest pr) {
	requests.add(pr);
	this.notifyAll();
}
// ElevatorP.java
// getCtrl()返回共享对象
synchronized (getCtrl()) {
	for (PersonRequest x: getCtrl().getRequests()) {
		char from = x.getFromBuilding();
		char to = x.getToBuilding();
		if (((switchInfo >> (from - 'A')) & 1) +
			((switchInfo >> (to - 'A')) & 1) == 2) {
			return false;
		}
	}
}

在第一次作业中,我的共享对象全部是同一个类的实例,且共享对象之间不会有互相访问的情况。因此,用最粗暴的方法“只要涉及共享对象,全部上锁!”不会导致死锁。

从第二次作业开始,我将原来的生产-消费模式中的一级托盘重构为二级托盘。因此在实现时特别留意,防止两类共享对象肆意加锁导致的死锁。具体策略如下:

// GlobalController.java
// 一级托盘:GlobalController,二级托盘:Controller
public synchronized void infoInputKilled() {
	this.inputAlive = false;
	for (Controller ctrl : controllers.values()) {
		synchronized (ctrl) {
 			ctrl.setInputAlive(false);
 			ctrl.notifyAll();
		}
 	}
}
// Elevator.java
// gctrl为一级托盘对象,ctrl为二级托盘对象
boolean transEnd = gctrl.withoutTransfers();	// 在二级托盘同步块外调用一级托盘
synchronized (ctrl) {
	if ((ctrl.getRequests().isEmpty() || specialWait()) && direction == 0) {
		if (ctrl.isInputAlive() || !transEnd) {		// *
			...
        } else { return; }
	} else {
        ...
    }
}

由于我的同步块内基本上都是读写并举,改用读写锁的轻量化意义不大,所以全程只用了 synchronized 的方式上锁。

标签:OO,2.0,1.0,BUAA,Elevator,Controller,GlobalController,PersonRequest,Unit
来源: https://www.cnblogs.com/ChorlingLau/p/16197054.html