《python线程教程,python线程学习笔记.doc》由会员分享,可在线阅读,更多相关《python线程教程,python线程学习笔记.doc(6页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、线程访问全局变量import threadingg_num = 0def test(n): global g_num for x in range(n): g_num += x g_num -= x print(g_num)if _name_ = _main_: t1 = threading.Thread(target=test, args=(10,) t2 = threading.Thread(target=test, args=(10,) t1.start() t2.start()在一个进程内的所有线程共享全局变量,很方便在多个线程间共享数据。缺点就是,线程是对全局变量随意遂改可能造成多线
2、程之间对全局变量的混乱(即线程非安全)。线程的安全问题import threadingimport timeticket = 20def sell_ticket(): global ticket while True: if ticket 0: time.sleep(0.5) ticket -= 1 print(卖了一张票,还剩.format(threading.current_thread().name, ticket) else: print(票卖完了.format(threading.current_thread().name) breakfor i in range(5): t = t
3、hreading.Thread(target=sell_ticket, name=thread-.format(i + 1) t.start()同步当多个线程几乎同时修改某一个共享数据的时候,需要进行同步控制。同步就是协同步调,按预定的先后次序进行运行。线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制是引入互斥锁。互斥锁互斥锁为资源引入一个状态:锁定/非锁定某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的
4、正确性。threading模块中定义了Lock类,可以方便的处理锁定:# 创建锁mutex = threading.Lock()# 锁定mutex.acquire()# 释放mutex.release()注意: 如果这个锁之前是没有上锁的,那么acquire不会堵塞如果在调用acquire对这个锁上锁之前 它已经被 其他线程上了锁,那么此时acquire会堵塞,直到这个锁被解锁为止。和文件操作一样,Lock也可以使用with语句快速的实现打开和关闭操作。使用互斥锁解决卖票问题import threadingimport timeticket = 20lock = threading.Lock(
5、)def sell_ticket(): global ticket while True: lock.acquire() if ticket 0: time.sleep(0.5) ticket -= 1 lock.release() print(卖了一张票,还剩.format(threading.current_thread().name, ticket) else: print(票卖完了.format(threading.current_thread().name) lock.release() breakfor i in range(5): t = threading.Thread(tar
6、get=sell_ticket, name=thread-.format(i + 1) t.start()上锁过程:当一个线程调用锁的acquire()方法获得锁时,锁就进入“locked”状态。每次只有一个线程可以获得锁。如果此时另一个线程试图获得这个锁,该线程就会变为“blocked”状态,称为“阻塞”,直到拥有锁的线程调用锁的release()方法释放锁之后,锁进入“unlocked”状态。线程调度程序从处于同步阻塞状态的线程中选择一个来获得锁,并使得该线程进入运行(running)状态。总结锁的好处: 确保了某段关键代码只能由一个线程从头到尾完整地执行锁的坏处: 阻止了多线程并发执行,
7、包含锁的某段代码实际上只能以单线程模式执行,效率就大大地下降了。 由于可以存在多个锁,不同的线程持有不同的锁,并试图获取对方持有的锁时,可能会造成死锁。线程间通信线程之间有时需要通信,操作系统提供了很多机制来实现进程间的通信,其中我们使用最多的是队列Queue.Queue的原理Queue是一个先进先出(First In First Out)的队列,主进程中创建一个Queue对象,并作为参数传入子进程,两者之间通过put( )放入数据,通过get( )取出数据,执行了get( )函数之后队列中的数据会被同时删除,可以使用multiprocessing模块的Queue实现多进程之间的数据传递。im
8、port threadingimport timefrom queue import Queuedef producer(queue): for i in range(100): print(存入了.format(threading.current_thread().name, i) queue.put(i) time.sleep(0.1) returndef consumer(queue): for x in range(100): value = queue.get() print(取到了.format(threading.current_thread().name, value) tim
9、e.sleep(0.1) if not value: returnif _name_ = _main_: queue = Queue() t1 = threading.Thread(target=producer, args=(queue,) t2 = threading.Thread(target=consumer, args=(queue,) t3 = threading.Thread(target=consumer, args=(queue,) t4 = threading.Thread(target=consumer, args=(queue,) t6 = threading.Thre
10、ad(target=consumer, args=(queue,) t1.start() t2.start() t3.start() t4.start() t6.start()多线程版聊天import socketimport threadings = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)s.bind(0.0.0.0, 8080)def send_msg(): ip = input(请输入您要聊天的ip:) port = int(input(请输入对方的端口号:) while True: msg = input(请输入聊天内容:) s
11、.sendto(msg.encode(utf-8), (ip, port) if msg = bye: ip = input(请输入您要聊天的ip:) port = int(input(请输入对方的端口号:)def recv_msg(): while True: content, addr = s.recvfrom(1024) print(接收到了主机端口的消息:.format(addr0, addr1, content.decode(utf-8),file=open(history.txt, a, encoding=utf-8)send_thread = threading.Thread(target=send_msg)recv_thread = threading.Thread(target=recv_msg)send_thread.start()recv_thread.start()