UUID是如何保证唯一性
高可靠,32位16进制数,32*4=128位二进制数,UUID4重复概率1/(2^128),加上时间戳应该好点,UUID1好点。
UUID Version 1:基于时间的UUID
时间戳、随机数和机器MAC地址得到。常用
UUID Version 2:DCE安全的UUID
UUID1的时间戳前4位置换为POSIX的UID或GID
UUID Version 3:基于名字的UUID(MD5)
计算名字和名字空间的MD5散列值得到,相同名字空间中相同名字的UUID重复生成是相同的。
UUID Version 4:随机UUID
随机数。
UUID Version 5:基于名字的UUID(SHA1)
计算名字和名字空间的SHA1值得到。
Python线程同步
昨天面试了一家造汽车的单位,我果然啥都不会via,几分钟就结束了,觉得Python线程同步肯定有用吧,记一下。
临界资源
就是只能有一个线程访问的一块代码,需要进行原子操作的那部分。
1通过锁:threading.Lock
线程共享Num类,访问前需要先获得锁。防止加法出错。另外,RLock
操作可重入,同一个线程内多次acquire(),
程序不会堵塞,但是需要相同的release。
import threading
import time
class Num:
def __init__(self):
self.num = 0
self.lock = threading.Lock()
def add(self):
self.lock.acquire() # 加锁,锁住相应的资源
self.num = 1
self.lock.release() # 解锁,离开该资源
n = Num()
class jdThread(threading.Thread):
def __init__(self):
super().__init__()
def run(self):
for i in range(10000000):
n.add()
if __name__ == '__main__':
list_thread = [jdThread() for i in range(2)]
[t.start() for t in list_thread]
[t.join() for t in list_thread]
print(n.num)
2.信号量threading.Semaphore
控制同时访问的个数,在执行IO密集型任务时。另外,boundageSamephore用于超过release时的抛出异常。
代码语言:javascript复制import threading
import time
class Num:
def __init__(self):
self.num = 0
self.sem = threading.Semaphore(value=1)
def add(self):
self.sem.acquire() # 加锁,锁住相应的资源
print(self.num)
time.sleep(0.1)
self.sem.release() # 解锁,离开该资源
n = Num()
class jdThread(threading.Thread):
def __init__(self):
super().__init__()
def run(self):
for i in range(10):
n.add()
if __name__ == '__main__':
list_thread = [jdThread() for i in range(2)]
[t.start() for t in list_thread]
[t.join() for t in list_thread]
print(n.num)
3.条件量threading.Condition()
生产者消费者模式,wait进入等待状态,notify恢复运行
代码语言:javascript复制import threading
import time
class Goods: # 产品类
def __init__(self):
self.count = 0
def add(self, num=1):
self.count = num
def sub(self):
if self.count > 0:
self.count -= 1
def empty(self):
return self.count <= 0
class Producer(threading.Thread): # 生产者类
def __init__(self, condition, goods, sleeptime=1): # sleeptime=1
threading.Thread.__init__(self)
self.cond = condition
self.goods = goods
self.sleeptime = sleeptime
def run(self):
cond = self.cond
goods = self.goods
for i in range(1000):
time.sleep(self.sleeptime)
cond.acquire()
goods.add()
print("产品数量:", goods.count, "生产者线程")
cond.notifyAll() # 唤醒所有等待的线程,唤醒消费者进程
cond.release()
class Consumer(threading.Thread): # 消费者类
def __init__(self, condition, goods, sleeptime=2): # sleeptime=2
threading.Thread.__init__(self)
self.cond = condition
self.goods = goods
self.sleeptime = sleeptime
def run(self):
cond = self.cond
goods = self.goods
while True:
cond.acquire() # 锁住资源
if goods.empty(): # 如无产品则让线程等待
cond.wait()
goods.sub()
print("产品数量:", goods.count, "消费者线程")
cond.release() # 解锁资源
if __name__ == '__main__':
g = Goods()
c = threading.Condition()
list_pro = [Producer(c, g) for _ in range(2)]
[p.start() for p in list_pro]
list_pro = [Consumer(c, g) for _ in range(5)]
[p.start() for p in list_pro]
4.队列queue
线程内的消息队列import queue,进程内的消息队列from multiprocessing import Queue,
代码语言:javascript复制import threading
import queue
import time
class jdThread(threading.Thread):
def __init__(self, index, queue):
threading.Thread.__init__(self)
self.index = index
self.queue = queue
def run(self):
while True:
time.sleep(1)
item = self.queue.get()
if item is None:
break
print("序号:", self.index, "任务", item, "完成")
self.queue.task_done() # task_done方法使得未完成的任务数量-1
if __name__ == '__main__':
q = queue.Queue(0)
for i in range(2):
jdThread(i, q).start() # 两个线程同时完成任务
for i in range(10):
q.put(i) # put方法使得未完成的任务数量 1