一、设定场景
想象你在玩一个RPG游戏,队伍里有一个大BOSS,BOSS有10格血量。
现在有很多玩家(线程)可以同时攻击BOSS,但每次最多只能有3个人同时攻击,否则BOSS会暴走(系统崩溃)。
二、信号量的角色
- 信号量就像BOSS身边的“护卫队长”,他手里有3个“攻击令牌”。
- 只有拿到令牌的玩家,才能上去攻击BOSS。
- 其他玩家只能在旁边等,等有人打完归还令牌,才有机会上去。
三、攻击流程(信号量的工作原理)
- 玩家A、B、C同时冲上去,护卫队长各发给他们一个令牌,他们可以攻击BOSS。
- 玩家D、E也想上去,但令牌已经发完了,只能在旁边排队等。
- A打完了,把令牌还给护卫队长,队长立刻把令牌发给排队最久的D,D可以上去攻击。
- 以此类推,始终只有3个人能同时攻击BOSS。
四、血量属性的变化
- 每个玩家攻击一次,BOSS的血量就减少1格。
- 由于护卫队长(信号量)控制着攻击人数,不会出现一堆人一拥而上把BOSS打挂了还在打,也不会让BOSS暴走。
- 这样既保证了BOSS的血量变化是安全的,又让大家都有机会参与攻击。
五、代码小例子(伪代码)
import threading
import time
# BOSS有10格血量
boss_hp = 10
# 最多3个人同时攻击
semaphore = threading.Semaphore(3)
lock = threading.Lock() # 控制血量安全减少
def attack(player):
global boss_hp
semaphore.acquire() # 护卫队长发令牌
print(f"{player} 获得攻击令牌,开始攻击BOSS")
time.sleep(1) # 攻击需要1秒
with lock:
if boss_hp > 0:
boss_hp -= 1
print(f"{player} 攻击成功,BOSS剩余血量:{boss_hp}")
else:
print(f"{player} 攻击时BOSS已倒下")
semaphore.release() # 归还令牌
for i in range(8):
threading.Thread(target=attack, args=(f"玩家{i+1}",)).start()
六、总结
- 信号量就像BOSS身边的护卫队长,手里有固定数量的“攻击令牌”。
- 只有拿到令牌的玩家才能攻击BOSS,保证了同时攻击BOSS的人数不会超过上限,BOSS的血量变化也不会混乱。
- 这样既保证了游戏公平,也保证了系统安全!