Python如何实现线程间同步[python高级]

线程间同步

如果多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性,需要对多个线程进行同步。

使用Thread对象的Lock和Rlock可以实现简单的线程同步,这两个对象都有acquire方法和release方法,对于那些需要每次只允许一个线程操作的数据,可以将其操作放到acquire和release方法之间。

需要注意的是,Python有一个GIL(Global Interpreter Lock)机制,任何线程在运行之前必须获取这个全局锁才能执行,每当执行完100条字节码,全局锁才会释放,切换到其他线程执行。

线程同步问题

多线程实现同步有四种方式:

锁机制,信号量,条件判断和同步队列。

下面我主要关注两种同步机制:锁机制和同步队列。

(1)锁机制

threading的Lock类,用该类的acquire函数进行加锁,用realease函数进行解锁

    import threading

    import time

    class myThread(threading.Thread):

       def __init__(self, threadID, name, counter):

          threading.Thread.__init__(self)

          self.threadID = threadID

          self.name = name

          self.counter = counter

       def run(self):

          print("Starting " + self.name)

          # 获得锁,成功获得锁定后返回True

          # 可选的timeout参数不填时将一直阻塞直到获得锁定

          # 否则超时后将返回False

          threadLock.acquire()

          print_time(self.name, self.counter, 5)

          # 释放锁

          threadLock.release()

    def print_time(threadName, delay, counter):

       while counter:

          time.sleep(delay)

          print("%s: %s" % (threadName, time.ctime(time.time())))

          counter -= 1

        

    threadLock = threading.Lock()

    threads = []

    # 创建新线程

    thread1 = myThread(1, "Thread-1", 1)

    thread2 = myThread(2, "Thread-2", 2)

    # 开启新线程

    thread1.start()

    thread2.start()

    # 添加线程到线程列表

    threads.append(thread1)

    threads.append(thread2)

    # 等待所有线程完成

    for t in threads:

       t.join()

    

    print("Exiting Main Thread")

(2) 线程同步队列queue

python2.x中提供的Queue, Python3.x中提供的是queue

见import queue.

Python的queue模块中提供了同步的、线程安全的队列类,包括FIFO(先入先出)队列Queue,LIFO(后入先出)队列LifoQueue,和优先级队列PriorityQueue。这些队列都实现了锁原语,能够在多线程中直接使用。可以使用队列来实现线程间的同步。

相关推荐:《Python相关教程》

queue模块中的常用方法:

queue.qsize() 返回队列的大小

queue.empty() 如果队列为空,返回True,反之False

queue.full() 如果队列满了,返回True,反之False

queue.full 与 maxsize 大小对应

queue.get([block[, timeout]])获取队列,timeout等待时间

queue.get_nowait() 相当Queue.get(False)

queue.put(item) 写入队列,timeout等待时间

queue.put_nowait(item) 相当Queue.put(item, False)

queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号

queue.join() 实际上意味着等到队列为空,再执行别的操作

案例1:

  import queue

    import threading

    import time

    

    exitFlag = 0

    

    class myThread(threading.Thread):

       def __init__(self, threadID, name, q):

          threading.Thread.__init__(self)

          self.threadID = threadID

          self.name = name

          self.q = q

    

       def run(self):

          print("Starting " + self.name)

          process_data(self.name, self.q)

          print("Exiting " + self.name)

    

    def process_data(threadName, q):

       while not exitFlag:

          queueLock.acquire()

          if not workQueue.empty():

             data = q.get()

             queueLock.release()

             print("%s processing %s" % (threadName, data))

          else:

             queueLock.release()

          time.sleep(1)

    

    threadList = ["Thread-1", "Thread-2", "Thread-3"]

    nameList = ["One", "Two", "Three", "Four", "Five"]

    queueLock = threading.Lock()

    workQueue = queue.Queue(10)

    threads = []

    threadID = 1

    

    # 创建新线程

    for tName in threadList:

       thread = myThread(threadID, tName, workQueue)

       thread.start()

       threads.append(thread)

       threadID += 1

    

    # 填充队列

    queueLock.acquire()

    for word in nameList:

       workQueue.put(word)

    queueLock.release()

    

    # 等待队列清空

    while not workQueue.empty():

       pass

    

    # 通知线程是时候退出

    exitFlag = 1

    

    # 等待所有线程完成

    for t in threads:

       t.join()

    print("Exiting Main Thread")

案例2:

    import time

    import threading

    import queue

    

    class Worker(threading.Thread):

        def __init__(self, name, queue):

            threading.Thread.__init__(self)

            self.queue = queue

            self.start()    #执行run()

    

        def run(self):

            #循环,保证接着跑下一个任务

            while True:

                # 队列为空则退出线程

                if self.queue.empty():

                    break

                # 获取一个队列数据

                foo = self.queue.get()

                # 延时1S模拟你要做的事情

                time.sleep(1)

                # 打印

                print(self.getName() + " process " + str(foo))

                # 任务完成

                self.queue.task_done()

    

    

    # 队列

    queue = queue.Queue()

    # 加入100个任务队列

    for i in range(100):

        queue.put(i)

    # 开10个线程

    for i in range(10):

        threadName = 'Thread' + str(i)

        Worker(threadName, queue)

    # 所有线程执行完毕后关闭

    queue.join()

相关推荐:

Python如何进行线程切换

以上是 Python如何实现线程间同步[python高级] 的全部内容, 来源链接: utcz.com/z/540350.html

回到顶部