运维开发网

python3高级系列03:进程和线程(下)

运维开发网 https://www.qedev.com 2021-02-27 08:29 出处:51CTO 作者:mb5fdb0a4002420
创建线程上一小节我们讲了进程的创建,线程的创建和进程非常类似,使用threading模块的Thread类,我们使用简短的示例看下。from threading import Threadimport threadingimport ost1 = Thread(name='t1',target=lambda x:print(x,os.getpid(),threading.current_thread

python3高级系列03:进程和线程(下)

创建线程

上一小节我们讲了进程的创建,线程的创建和进程非常类似,使用threading模块的Thread类,我们使用简短的示例看下。

from threading import Thread

import threading

import os

t1 = Thread(name='t1',target=lambda x:print(x,os.getpid(),threading.current_thread().name),args=('小麦',))

t1.start()

基本和Process类似,这里的target没有写函数了,使用lambda表达式。

python3高级系列03:进程和线程(下)

python3高级系列03:进程和线程(下)

线程共享全局变量

下面我们使用继承Thread的方式,定义自己的线程子类,为了少贴些代码,这里我们顺带验证下同进程内线程是否可以共享全局变量。

import threading,time,os,random

class MyThread(threading.Thread):

  def __init__(self,name):

    threading.Thread.__init__(self,name=name)

  def run(self):

    global amount

    amount -= 100

    sleep = random.randint(1,5)

    time.sleep(sleep)

    print(self.name,amount,sleep)

amount = 1000

if __name__ == '__main__':

  print('main',amount)

  m1 = MyThread('m1')

  m2 = MyThread('m2')

  m1.start()

  m2.start()

  m1.join()

  m2.join()

运行结果可以看到,线程m1和m2是可以共享全局变量的,但是结果不符合预期,m1和m2获取到的amount值都是800。可以得出结论,同一个进程内的线程可以共享全局变量,但是多个线程同时修改共享数据,会出现数据混乱或产生错误数据。

python3高级系列03:进程和线程(下)

python3高级系列03:进程和线程(下)

线程同步

由于多个线程是独立运行的,且每个线程都可以访问共享变量数据,所以当多个线程同时修改共享数据变量时,就会大概率产生数据不一致问题。为了保证数据的正确性,需要对多个线程进行同步。

线程同步即线程一个个按顺序访问共享数据,单个线程修改共享数据时,先将其锁定,此时其他线程不得访问该共享数据,直到该线程操作完成,释放锁资源,保证每次只有一个线程访问共享数据。

下面我们使用threading.Lock对临界资源进行上锁。

import threading

class MyThread(threading.Thread):

  def run(self):

    global amount

    lock.acquire()

    ...

    lock.release()

amount = 1000

lock = threading.Lock()

我们对上面的程序进行小小的改造,使用lock锁定临界资源,为了少贴代码,这里只贴出锁相关代码片段,运行可以看到结果符合预期。

python3高级系列03:进程和线程(下)

python3高级系列03:进程和线程(下)

线程间使用队列通信

上一节我们使用Queue在进程间通信,在线程间也可以使用队列来通信,这里我们使用queue模块的Queue。

我们用一个生产者-消费者程序模拟两个线程往队列写数据,从队列读数据。

from queue import Queue

from threading import Thread

class Product(Thread):

  def __init__(self, queue):

    Thread.__init__(self)

    self.queue = queue

  def run(self):

    for item in ['python', 'pycharm', 'pygame', 'tkinter', 'django']:

      self.queue.put(item)

      print(self.name,'product',item)

class Consume(Thread):

  def __init__(self, queue):

    Thread.__init__(self)

    self.queue = queue

  def run(self):

    while not self.queue.empty():

      print(self.name, 'consume',self.queue.get())

if __name__ == '__main__':

  queue = Queue()

  p,c = Product(queue),Consume(queue)

  p.start()

  c.start()

  p.join()

  c.join()

python3高级系列03:进程和线程(下)

python3高级系列03:进程和线程(下)

小结

进程是程序运行的一个实例,线程是进程内执行任务的一个实例,线程是CPU调度和分配的最小单位;不同进程之间无法共享数据,同一个进程内线程共享进程的资源,一个进程崩溃不会影响其他进程,而由于线程在进程中,线程的奔溃可能会导致进程奔溃;线程间如果存在共享资源并发访问,需要对临界资源上锁,如果是非共享数据则不需要线程同步。

扫码领视频副本.gif

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号