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

时间:2014-01-03 17:57:13

标签: 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()

结果:

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
......
......

我是python的新手,并搜索了很多关于线程,Lock和RLock的信息,但没有运气。 哪里错了?

1 个答案:

答案 0 :(得分:3)

要使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()

有些注意事项:

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