年底裁员新套路,leader找下属说有裁员名额,让你选择自己走,过几天再说裁员名额取消了,一分赔偿不用给!
刚看到个贴子,说有公司年底裁员出新套路:leader叫你谈话,说现在有裁员名额,让你“体面选择自己走”,你一犹豫签了,过几天又说名额取消,公司一分钱赔偿不用给。
本质就是变相逼你主动离职,好省赔偿,还想把道德绑在你身上,让你觉得不走是不讲大局。换个角度想,这种公司不离开才是风险。
从我的角度看,碰上这种情况,三个建议:一是别急着签“自愿离职”,所有说法都让领导写进邮件或通知;二是多问问劳动法、咨询专业机构;三是手里要有plan B,能力和履历都准备好。
公司算的是成本,我们要守的是底线,既要懂维权,也要有转身的能力。
算法题:打印零与奇偶数
昨晚加班到十点多,坐地铁回家的时候刷题,刷到一个看着不难、写起来一直踩坑的并发题,就是那个“打印零与奇偶数”。一开始我还以为是简单 for 循环,结果一看要求:三个线程一起配合打印,脑子一下就清醒了。
简单说一下哈,题意大概这样:
给你一个正整数 n,要打印出这样一串数字:0102030405... 一直到 n。
注意有三个线程:
一个线程只打印 0 一个线程只打印奇数 一个线程只打印偶数
目标是三个线程一起跑,但是输出顺序必须是:0,1,0,2,0,3,... 这样交替,不能乱。
用人话说,就是你开了三个工人,一个管打 0,一个管打奇数,一个打偶数,大家不能抢话,得排队说话。
这个题关键点不是“怎么打印数字”,而是“啥时候轮到谁打印”。线程之间要有一个“约定”:现在该 0 说话了,还是该奇数,还是该偶数。
在 Python 里,比较顺手的是 threading.Semaphore 这种信号量。可以理解成一个门,拿到 permit 的线程才能过门,没拿到就得老老实实在门口等。
这里可以设计三个信号量:
zero_sem:轮到打印 0 的时候放行odd_sem:轮到打印奇数的时候放行even_sem:轮到打印偶数的时候放行
一开始肯定是先打印 0,所以 zero_sem 初始值设为 1,另外两个设为 0,让它们先等着。
整个配合过程大致是这样一种节奏:
打 0 的线程醒来,打印一个 0 看下一个数字是奇数还是偶数 如果是奇数,就把 odd_sem打开一下;如果是偶数,就打开even_sem奇数/偶数线程被放行,打印完自己的数,再把 zero_sem打开,让 0 线程继续下一轮
这样来回交替,就能保证输出顺序了。
上代码,用 Python 写一个类,把逻辑都包进去,会比较清晰一点:
import threading
classZeroEvenOdd:
def__init__(self, n: int):
self.n = n
# 一开始轮到 zero 打,所以给 1
self.zero_sem = threading.Semaphore(1)
self.even_sem = threading.Semaphore(0)
self.odd_sem = threading.Semaphore(0)
defzero(self, printNumber):
"""
printNumber(x) 负责把数字 x 打出来,这个在外面传进来
"""
for i in range(1, self.n + 1):
self.zero_sem.acquire() # 等轮到自己
printNumber(0)
# 下一个是奇数还是偶数
if i % 2 == 1:
self.odd_sem.release()
else:
self.even_sem.release()
defodd(self, printNumber):
for i in range(1, self.n + 1, 2):
self.odd_sem.acquire() # 等 zero 叫自己
printNumber(i)
self.zero_sem.release() # 打完把机会还给 zero
defeven(self, printNumber):
for i in range(2, self.n + 1, 2):
self.even_sem.acquire()
printNumber(i)
self.zero_sem.release()
上面只是把逻辑写完了,还得真的起三个线程跑起来,外面可以这么写一个小 demo:
defprintNumber(x):
# 不换行连续打印
print(x, end='')
if __name__ == "__main__":
n = 5
zeo = ZeroEvenOdd(n)
t_zero = threading.Thread(target=zeo.zero, args=(printNumber,))
t_odd = threading.Thread(target=zeo.odd, args=(printNumber,))
t_even = threading.Thread(target=zeo.even, args=(printNumber,))
t_zero.start()
t_odd.start()
t_even.start()
t_zero.join()
t_odd.join()
t_even.join()
# 输出:0102030405
跑完输出就是 0102030405 这种形态。你可以把 n 改大一点试试,节奏是一样的。
这个题最容易出事的地方,其实就是“两个线程一起打印”,结果顺序乱了。上面这套写法不乱的原因主要就两个点:
一是任何时刻,只有一个信号量是“通”的。 起始状态只有 zero_sem = 1,所以一定是 zero 线程先打 0;打完以后,它根据 i 的奇偶只放行一个信号量,要么 odd,要么 even,绝对不会两边都打开。
二是每个数字线程打印完都会把控制权还给 zero。 奇数 / 偶数线程打印完自己那一个数字,第一件事就是 self.zero_sem.release(),等 zero 再来决定下一步。谁也不能跳过 zero 自作主张。
你可以想象成一个主持人(zero 线程)和两个嘉宾(odd / even)。主持人永远控制节奏:先自己说一句 0,再点名“奇数嘉宾发言”,等他说完,再说 0,再点名“偶数嘉宾发言”……只要主持人不乱点名,场面就不会失控。
-END-
我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html
虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB