309
社区成员
发帖
与我相关
我的任务
分享第一次作业(hw5)基本上全部给方法都加上了同步块。
第二次作业(hw6)想尝试使用上课提到的读写锁,不过最后好像只有 floor 等少数几个地方用上了。然后再和同学跑评测机的时候发现效率仍然很慢,于是开始尝试缩小同步块,主要分析过程是:这个方法会被哪些线程调用?涉及到哪些数据?这些数据会不会被中途修改?如果都是读或者写的时候互斥,我会尝试去掉 synchronized ,或者缩小 synchronized 的范围
第三次作业(hw7)由于加了双轿厢,然后发现可以对整个电梯进行再次细分,从原来的Elevator-ElevatorThread-Adviser 进一步分出轿厢、轿厢控制、输出类,减少每个流程持锁时间,分散了数据。除此之外对于锁与同步块的设置思路没有较大改变。
总而言之,就是在保证安全的情况下最小化同步块,锁往往就是同步块中处理语句需要修改或者读取的对象或者变量。
等待请求输入
调用策略获取应该投放给的电梯(若没有置为 -1)
若电梯 id 不为 1,投放给相应电梯(电梯 add 内部持锁)
对于请求的选择,优先改造、回收、维修工,然后为乘客请求设置 PriorityQueue ,采取 Time > restDis > weight 的比较规则,尽可能让乘客等待时间短。
对于被赶下来的乘客,则实现 addPoorGuy 方法,放入同一个优先队列,即对是否上过电梯不做区分。
使用 evaluateScore 评估是否适合将某请求发送给相应乘客,分数越小说明越合适。
惩罚: 负载、距离、换乘、双轿厢协调
奖励: 同方向
排列后选择最适合的电梯分配。
主要出现过以下几类 bug 和相应解决方案:
提前结束:增加 run 循环中的判断信息,确定不会再有新的请求进入该环节
未正常结束:设置 end 标记表示输入已结束
死锁:根据同步互斥条件检查
在不允许的状态下接客:修改分配器分配策略
关于多线程程序的线程问题,很难直接看出来。一般是评测机测出错误之后,用大模型分析输出记录,找到违反限制的记录,然后再追溯到相关的数据与方法。
线程安全相关问题主要分为两个方向:冲突,死锁。
对于冲突,需要仔细思考每个方法,如果他需要修改或读取一个可能被其他进程修改的数据,应该锁起来再操作。
对于死锁,需要减小持锁时间,层次化设计以划清职责,尽可能减少循环依赖。
层次化设计的核心:高内聚低耦合。具体而言:
尽可能缩小职责范围
用接口抽象行为
类之间的交互尽量不要跨层
工具: Chatgpt 5.4 chat 用于指导建议和知识补充;trae(Kimi-K2.5) 用于代码补全;codex(gpt 5.4) 用于 debug 、写评测机
工作流:
阅读题目,列一个简单的 TODO.md 和类草图
将初步设计发给 Chatgpt ,审查设计,提供指导意见和易错点分析 tutorial.md
在 trae(Kimi-K2.5) 开发,具体分工是定义好类名、数据名和方法名,如果比较简单的方法手动编写;如果比较复杂,用自然语言描述相关过程,由大模型编写后,人工审查
完成单类编写后,用 Kimi-K2.5 编写单元测试
完成全部内容后,先提交一版获取课程平台数据,如果有 bug 就使用 codex(gpt 5.4) 分析并修改
用 codex(gpt 5.4) 编写评测机,与其他同学的程序进行测试,并修复 bug 并修改提高性能
优势: 主要是大模型从输出中定位错误会比较强势,如果人肉搜索应该比较困难
困难: 受限于我的提示词能力和模型本身的能力,会出现我说我的它做它的情况,需要不断返工并指正,某些情况下不如自己完成
感受: 整体而言,不再纠结于语言具体的细节和 bug 的定位,能更关注于架构设计和算法
第二单元在实现方面比较困难,最终我的架构已经涉及二十多个类,两千行代码,作为初尝多线程的我来说还是很有挑战性的。
但是之前交流群里提到其实电梯可以不用多线程实现,我思考了一下,由于只有一个输入线程,而且电梯的动作也是通过 sleep 来模拟,或许只需要维护一个“线程”队列,即可单线程实现,而且性能上感觉不会差太多。
所以或许可以引入更真实的题目设计?(如果真加了未来的学弟学妹不要怪我)