[PyQt] Are QThreads compatible with python's threading.RLock?

Darren Dale dsdale24 at gmail.com
Sun Apr 3 16:56:01 BST 2011


On Sat, Jul 26, 2008 at 3:48 AM, Phil Thompson
<phil at riverbankcomputing.com> wrote:
> On Fri, 25 Jul 2008 17:41:22 -0400, Darren Dale <dsdale24 at gmail.com> wrote:
>> I use a library that provides rudimentary thread safety of its objects
> and
>> file
>> I/O using threading.RLock from the python standard library. Could anyone
>> tell
>> me if PyQt4's QThreads are compatible with these recursive locks?
>
> Other than the fact that they will both be implemented using the same OS
> primitives, Python's and Qt's threading know nothing about each other.

I had a reason to reeducate myself on this issue again today, since I write
interfaces with PyQt4 but also rely upon third-party task managers and
multiprocessing pools that are implemented with Python Threads and
Locks. I believe the answer to my original question is: Yes, Python's
Threads will respect PyQt4's locks (QMutex, QReadWriteLock) and
PyQt4's QThread will respect Python's threading.RLock.

Perhaps this conclusion is obvious to everyone but me. The script that
convinced me is appended. It requires argparse (part of the stdlib in
python-2.7), do "python test_locks.py -h" for help. Any of the
following shows that one of the threads waits while the other holds
the lock:

python test_locks.py
python test_locks.py -t
python test_locks.py -l
python test_locks.py -t -l

Whereas, if locking is disabled entirely, threading execution is no
longer synchronized (as expected):

python test_locks.py -d

I have tested with python-2.7 and PyQT4-4.8.3 linux and wuindows. I
also tested (on linux) a modified version of the script to use a
combination of Thread and QThread, which also works as one would hope.
If there are additional considerations I have overlooked, I would be
very interested to know.

Darren

---


import argparse
import sys
from threading import RLock, Thread
import time

from PyQt4.QtCore import QCoreApplication, QMutex, QThread, QReadWriteLock


class DummyLock(object):
   def acquire(self):
       pass
   def release(self):
       pass
   def __enter__(self):
       return self
   def __exit__(self, *args):
       pass


class QLock(QMutex):
   def acquire(self):
       self.lock()
   def release(self):
       self.unlock()
   def __enter__(self):
       self.acquire()
       return self
   def __exit__(self, *args):
       self.release()


class MyQThread(QThread):
   def __init__(self, id, lock):
       QThread.__init__(self)
       self.id = id
       self.lock = lock
   def run(self):
       for i in range(5):
           with self.lock:
               for i in range(5):
                   print self.id
                   time.sleep(0.1)
           time.sleep(0.01)


class MyThread(Thread):
   def __init__(self, id, lock):
       Thread.__init__(self)
       self.id = id
       self.lock = lock
   def run(self):
       for i in range(5):
           with self.lock:
               for i in range(5):
                   print self.id
                   time.sleep(0.1)
           time.sleep(0.01)


parser = argparse.ArgumentParser(
   description='test combinations of threads and locks'
   )
parser.add_argument(
   '-t', '--thread', action='store_const', const=MyQThread, default=MyThread,
   help='use QThread instead of threading.Thread'
   )
parser.add_argument(
   '-l', '--lock', action='store_const',
   const=QLock, default=RLock, help='use QMutex instead of threading.RLock'
   )
parser.add_argument(
   '-d', '--disable-lock', action='store_true', dest='disable_lock',
   help="don't use a lock of any kind"
   )
args = parser.parse_args()

if args.disable_lock:
   lock = DummyLock()
else:
   lock = args.lock()


thread1 = args.thread('Sid', lock)
thread1.start()
thread2 = args.thread('Nancy', lock)
thread2.start()

if args.thread is MyQThread:
   thread1.wait()
   thread2.wait()


More information about the PyQt mailing list