多线程在python中修改全局列表

phi*_*ree 5 python multithreading locking

我想在一个线程中每2秒将一个项目添加到全局列表中,并将列表保存到数据库中,然后在另一个线程中每3秒将其清空。

我创建了两个局部变量来监视添加的项总数和保存的项总数,它们应该每6秒钟相等,但事实并非如此。这是我的代码:

import datetime
import psutil,os,time
from threading import *
class AddToList(Thread):
    totalAdded=0
    def run(self):
        lock=RLock()
        lock.acquire()
        while True:
            entryList.append("AddToList at "+str(datetime.datetime.now()))
            self.totalAdded=self.totalAdded+len(entryList)
            print("totalAdded:"+str(self.totalAdded))
            time.sleep(2)
        lock.release()
class SaveList(Thread):
    totalSaved=0
    '''save entry to server'''
    def __init__(self):
        Thread.__init__(self)
    def run(self):
        lock=RLock()
        lock.acquire()
        while True:
            #save list to database,then empty the list
            self.totalSaved=self.totalSaved+len(entryList)
            del entryList[:]
            print("totalSaved:"+str(self.totalSaved))
            time.sleep(3)
        lock.release()

if __name__=="__main__":
    global entryList
    entryList=[]
    addClass= AddToList()
    addClass.start()
    saveClass=SaveList()
    saveClass.start()
Run Code Online (Sandbox Code Playgroud)

结果:

totalAdded:2
totalSaved:2
totalAdded:3
totalSaved:3totalAdded:4

totalAdded:6
totalSaved:5
totalAdded:7
totalSaved:6
totalAdded:8
totalAdded:10
totalSaved:8
totalAdded:11
totalSaved:9
totalAdded:12
totalAdded:14
totalSaved:11
totalAdded:15
totalSaved:12
...........
...........
totalAdded:51
totalSaved:39totalAdded:52

totalAdded:54
totalSaved:41
totalAdded:55
totalSaved:42
totalAdded:56
totalAdded:58
totalSaved:44
totalAdded:59
totalSaved:45totalAdded:60
......
......
Run Code Online (Sandbox Code Playgroud)

我是python的新手,并在线程,锁和RLock方面进行了大量搜索,但是没有运气。哪里错了?

sme*_*eso 5

要制作LockRLock工作,您必须在每个线程中使用相同的对象。锁定对象必须与要“保护”的对象具有相同的“可见性”。

这是您应该工作的新版本代码。它还避免使用全局变量等。

import datetime
import time
import threading

class AddToList(threading.Thread):

    def __init__(self, lock, entryList):
        threading.Thread.__init__(self)
        self.totalAdded = 0
        self.entryList = entryList
        self.lock = lock

    def run(self):
        while True:
            self.lock.acquire()
            entryList.append("AddToList at {}".format(datetime.datetime.now()))
            self.totalAdded += 1
            self.lock.release()
            print("totalAdded: {}".format(self.totalAdded))
            time.sleep(2)


class SaveList(threading.Thread):
    def __init__(self, lock, entryList):
        threading.Thread.__init__(self)
        self.totalSaved = 0
        self.entryList = entryList
        self.lock = lock

    def run(self):
        while True:
            self.lock.acquire()
            self.totalSaved += len(self.entryList)
            del self.entryList[:]
            self.lock.release()
            print("totalSaved: {}".format(self.totalSaved))
            time.sleep(3)


if __name__=="__main__":
    lock=threading.Lock()
    entryList=[]

    addClass = AddToList(lock, entryList)
    addClass.start()

    saveClass = SaveList(lock, entryList)
    saveClass.start()
Run Code Online (Sandbox Code Playgroud)

一些注意事项:

  1. 当您没有任何特殊需求时,请使用 Lock 而不是 RLock。RLock 要慢得多。
  2. 正如有人已经指出的那样,最好避免在不需要时使用全局变量。类变量也应该只在有意义的时候使用。
  3. 当您使用锁时,您应该尽量限制获取和释放之间的代码。在您之前的代码中,您永远不会释放锁。

  • `self.totalAdded += len(entryList)` 是错误的。您只添加了一项,而不是 `len(entryList)` 项。 (2认同)