代码之家  ›  专栏  ›  技术社区  ›  Corey Goldberg

多线程资源访问-锁放在哪里?

  •  5
  • Corey Goldberg  · 技术社区  · 17 年前

    我有线程代码,每个线程都需要写入同一个文件。为了防止并发问题,我使用了锁对象。

    我的问题是我是否正确使用了锁。如果我在每个线程内设置锁,那么该锁是全局的还是仅特定于该特定线程?

    基本上,我应该首先创建一个锁并将其引用传递给每个线程,还是像我在这里所做的那样从线程内部设置它

    import time
    from threading import Thread, Lock
    
    def main():
        for i in range(20):
            agent = Agent(i)
            agent.start()
    
    class Agent(Thread):
        def __init__(self, thread_num):
            Thread.__init__(self)
            self.thread_num = thread_num
    
        def run(self):
            while True:
                print 'hello from thread %s' % self.thread_num
                self.write_result()   
    
        def write_result(self):
            lock = Lock()
            lock.acquire()
            try:
                f = open('foo.txt', 'a')
                f.write('hello from thread %s\n' % self.thread_num)
                f.flush()
                f.close()
            finally:
                lock.release()
    
    if __name__ == '__main__':
        main()
    
    7 回复  |  直到 17 年前
        1
  •  6
  •   nosklo    17 年前

    对于您的用例,一种方法可以是编写 file

    class LockedWrite(file):
        """ Wrapper class to a file object that locks writes """
        def __init__(self, *args, **kwds):
            super(LockedWrite, self).__init__(*args, **kwds)
            self._lock = Lock()
    
        def write(self, *args, **kwds):
            self._lock.acquire()
            try:
                super(LockedWrite, self).write(*args, **kwds)
            finally:
                self._lock.release()
    

    要在代码中使用,只需替换以下函数:

    def main():
        f = LockedWrite('foo.txt', 'a')
    
        for i in range(20):
            agent = Agent(i, f)
            agent.start()
    
    class Agent(Thread):
        def __init__(self, thread_num, fileobj):
            Thread.__init__(self)
            self.thread_num = thread_num
            self._file = fileobj    
    
    #   ...
    
        def write_result(self):
            self._file.write('hello from thread %s\n' % self.thread_num)
    

    这种方法将文件锁定放在文件本身中,看起来更干净

        2
  •  3
  •   nosklo    17 年前

    class Agent(Thread):
        mylock = Lock()
        def write_result(self):
            self.mylock.acquire()
            try:
                ...
            finally:
                self.mylock.release()
    

    或者如果使用python>=2.5:

    class Agent(Thread):
        mylock = Lock()
        def write_result(self):
            with self.mylock:
                ...
    

    from __future__ import with_statement
    
        3
  •  1
  •   Igal Serban    17 年前

        4
  •  1
  •   Matthew Brubaker    17 年前

        5
  •  1
  •   Jeff Shannon    17 年前

    通过指定一个线程(可能是专门为此目的创建的)作为写入文件的唯一线程,并通过将要添加到文件中的字符串放入 queue.Queue 对象

    队列具有所有内置的锁定功能,因此任何线程都可以安全地调用 Queue.put() 随时都可以。文件编写器将是唯一调用的线程 Queue.get()

        6
  •  1
  •   Tim Cooper    14 年前

    锁实例应与文件实例相关联。

    换句话说,您应该同时创建锁和文件,并将它们传递给每个线程。

        7
  •  0
  •   Joseph Bui    17 年前

    我非常确定每个线程的锁必须是相同的对象。试试这个:

    import time
    from threading import Thread, Lock
    
    def main():
        lock = Lock()
        for i in range(20):
            agent = Agent(i, lock)
            agent.start()
    
    class Agent(Thread, Lock):
        def __init__(self, thread_num, lock):
            Thread.__init__(self)
            self.thread_num = thread_num
            self.lock = lock
    
        def run(self):
            while True:
                print 'hello from thread %s' % self.thread_num
                self.write_result()   
    
        def write_result(self):
            self.lock.acquire()
            try:
                f = open('foo.txt', 'a')
                f.write('hello from thread %s\n' % self.thread_num)
                f.flush()
                f.close()
            finally:
                lock.release()
    
    if __name__ == '__main__':
        main()