python线程和共享变量

时间:2010-11-06 20:34:01

标签: python thread-safety queue

如何在python中使用不同的threading.Thread更新共享变量?

假设我有5个线程处理Queue.Queue()。队列完成后我想做其他操作,但我希望它只发生一次。

是否可以共享和更新线程之间的变量。因此,当Queue.empty()为True时,此事件会被触发,但如果其中一个线程正在执行此操作,我不希望其他人也这样做,因为我会得到错误的结果。

修改
我有一个队列,反映文件系统上的文件。 文件由线程上传到站点,当每个线程上传文件时,它会更新我从文件中获得的一组()关键字。
当队列为空时,我需要联系该站点并告诉它更新关键字计数。现在每个线程都这样做,我得到每个线程的更新,这是坏的。 我也试图清空它,但它不起作用。

    keywordset = set()
    hkeywordset = set()
    def worker():
        while queue:
            if queue.empty():
                if len(keywordset) or len(hkeywordset):
                    # as soon as the queue is empty we send the keywords and hkeywords to the
                    # imageapp so it can start updating 
                    apiurl   = update_cols_url
                    if apiurl[-1] != '/':
                        apiurl = apiurl+'/'
                    try:
                        keywords = []
                        data = dict(keywords=list(keywordset), hkeywords=list(hkeywordset))
                        post = dict(data=simplejson.dumps(data))
                        post = urllib.urlencode(post)
                        urllib2.urlopen(apiurl, post)
                        hkeywordset.clear()
                        keywordset.clear()
                        print 'sent keywords and hkeywords to imageapp...'
                    except Exception, e: print e
            # we get the task form the Queue and process the file based on the action
            task = queue.get()
            print str(task)
            try:
                reindex = task['reindex']
            except:
                reindex = False
            data = updater.process_file(task['filename'], task['action'], task['fnamechange'], reindex)
            # we parse the images keywords and hkeywords and add them to the sets above for later 
            # processing
            try:
                for keyword in data['keywords']:
                    keywordset.add(keyword)
            except: pass
            try:
                for hkw in data['hkeywords']:
                        hkeywordset.add(hkw)
            except:pass
            queue.task_done()


    for i in range(num_worker_threads):
        t = threading.Thread(target=worker)
        t.daemon = True
        t.start()

    while 1:
        line = raw_input('type \'q\' to stop filewatcher... or \'qq\' to force quit...\n').strip()

这是我基本上尝试的。但是当然,queue.empty()的一部分与我拥有的线程一样多次被激活。

3 个答案:

答案 0 :(得分:0)

如果您正在使用队列来运行您的线程(thread pool),那么您确保不存在竞争条件(线程安全),因为队列以顺序方式运行您的线程,所以我认为你可以在线程之间共享一个变量,你可以确定在这个变量上没有竞争条件。

编辑:这里有类似关于你想做的事情希望这次能给你回答你的问题:):

import Queue
import threading
import ftplib
import os


class SendFileThread(threading.Thread):
     """ Thread that will handle sending files to the FTP server"""

     # Make set of keywords a class variable.
     Keywords = set()

     def __init__(self, queue, conn):

          self.conn = conn   
          self.queue = queue

          threading.Thread.__init__(self)

      def run(self):
          while True:
              # Grabs file from queue.
              file_name = self.queue.get()

              # Send file to FTP server.
              f=open(file_name,'rb')
              self.conn.storbinary('STOR '+os.path.basename(file_name),f)

              # Suppose that this keywords are in the first line.
              # Update the set of keywords.
              SendFileThread.Keywords.update(f.readline().split(" ")))

              # Signals to queue job is done.
              self.queue.task_done()


def main():
     # Files to send.
     files = os.listdir('/tosend')

     queue = Queue.Queue()

     # Connect to the FTP server.
     conn = ftplib.FTP('ftp_uri')   
     conn.login()

     # Create 5 threads that will handle file to send.
     for i in range(5):
         t = SendFileThread(queue, conn)
         t.start()

     # Fill the queue with files to be send.   
     for file in files:
         queue.put(file)

     # Wait until or thread are finish
     queue.join()

     # Send the keywords to the FTP server.
     # I didn't understand well the part update keywords count, 
     # how this count is stored ...
     # Here i will just send the keywords to the FTP server.
     with open("keywords", "w") as keywords_file
         keywords_file.write(";".join(SendFileThread.Keywords))
         conn.storbinary('STOR '+os.path.basename("keywords"),
                          keywords_file)

     conn.close()


if __name__ == '__main__':
     main()

答案 1 :(得分:0)

为什么不能将最后一步添加到队列中?

答案 2 :(得分:0)

在第一个队列为空之后,有另一个队列来放置此事件 或者对此活动有特殊的线索。