1进程-->n线程
多个线程共用进程资源
def func(n): ...... t = Thread(target=func, name = ‘‘, args = (1, ), kwargs = ‘‘) t.start()
class MyThread(Thread): def __init__(self, n): super(MyThread, self).__init__() self.n = n def run(self): ...... p = MyThread(args = (1,)) p.start()
重定义了run方法
进程共享数据与线程共享数据的区别
进程:每个进程中都有一份一样的数据
线程:共用同一份数据,可能导致数据安全性问题
ticket = 0 def task1(): global ticket for i in range(1000000): ticket += 1 print(‘task1-->‘, ticket) def task2(): global ticket for i in range(1000000): ticket += 2 print(‘task2-->‘, ticket) if __name__ == ‘__main__‘: t1 = threading.Thread(target=task1) t2 = threading.Thread(target=task2) t1.start() t2.start() t1.join() t2.join() print(ticket) ‘‘‘ 运行结果: task1--> 2014411 task2--> 2025288 2025288 ‘‘‘
共用了ticket,导致数据不安全,需要引入GIL锁
使线程变成伪线程:一个运行多个阻塞,交替运行。对于数据共享保证了安全性,但效率较低
lock = Lock()
lock.acquire()
......
lock.release()
lock = threading.Lock() ticket = 0 def task1(): global ticket lock.acquire() for i in range(1000000): ticket += 1 print(‘task1-->‘, ticket) lock.release() def task2(): global ticket lock.acquire() for i in range(1000000): ticket += 2 print(‘task2-->‘, ticket) lock.release() if __name__ == ‘__main__‘: t1 = threading.Thread(target=task1) t2 = threading.Thread(target=task2) t1.start() t2.start() t1.join() t2.join() print(ticket) ‘‘‘ task1--> 1000000 task2--> 3000000 3000000 ‘‘‘
加了锁之后,同样一个问题,可以保证数据安全,但是由于锁的存在,会使效率降低
出现多把锁,会出现死锁问题
示例:
lockA = Lock() lockB = Lock() class MyThread1(Thread): def __init__(self, name): super(MyThread1, self).__init__() self.name = name def run(self): if lockA.acquire(): # 若获取到值,返回true print(self.name+‘获取了A锁‘) time.sleep(0.2) # 转让cpu执行权,让另外的线程执行 if lockB.acquire(): print(self.name+‘获取了A锁和B锁‘) lockB.release() lockA.release() class MyThread2(Thread): def __init__(self, name): super(MyThread2, self).__init__() self.name = name def run(self): if lockB.acquire(): print(self.name+‘获取了B锁‘) time.sleep(0.2) if lockA.acquire(): print(self.name+‘获取了A锁和B锁‘) lockA.release() lockB.release() if __name__ == ‘__main__‘: t1 = MyThread1(‘线程1‘) t2 = MyThread2(‘线程2‘) t1.start() # 占有A锁且等待B锁 t2.start() # 占有B锁且等待A锁
t1,t2 出现占有且等待的阻塞条件,发生死锁
避免死锁的方法:
1.重构代码
2.给申请锁请求加timeout,lock.acquire(timeout=0.5)。如果0.5秒后还没有申请到锁,则返回False
生产者与消费者(利用队列) def produce(q): # 生产者 while True: ...... q.put(...) ...... q.put(None) # 队列尾端的标志 q.task_done() # 完成任务 def consume(q): while True: ...... item = q.get() ...... if item is None: # 表明到达队尾,退出队列 break q.task_done() # 完成任务 if __name__ == ‘__main__‘: q = queue.Queue(10) tp = threading.Thread(target=produce, args=(q,)) # 创建生产者 tc = threading.Thread(target=consume, args=(q,)) # 创建消费者 tp.start() tc.start() tp.join() # 先生产,后消费 tc.join()
原文:https://www.cnblogs.com/xiaoqichaoren/p/12268254.html