Search code examples
pythonpyqtqthreadqmutex

How to use QMutex correctly with QThread?


from PyQt5.QtCore import *
from PyQt5.QtWidgets import *


import time
import sys
import numpy as np

       

class Mainthread(QThread):

    def __init__(self, parent):
        super().__init__(parent)
        self.parent = parent
        self.running = None
        self.mutex = QMutex()



    def run(self):
                   
        while self.running:
            self.mutex.lock()
            print ("test")
            time.sleep(1)

            self.mutex.unlock()
                                                

class MainWindow(QMainWindow):

    def __init__(self):
        super().__init__()


        self.mainthread = Mainthread(self)
        self.mainthread.running = True
        self.mainthread.start()

        self.mainthread1 = Mainthread(self)
        self.mainthread1.running = True
        self.mainthread1.start()



    
app = QApplication(sys.argv)
mainwindow = MainWindow()
mainwindow.show()
app.exec_()

I have this code where I run two instances of the same MainThread class.

What I was expecting was that mainthread's message (which is "test") would print, then wait for a sec and then mainthread1's would be printed. Instead, it seems like both threads are running at the same time. Is there something I'm missing?


Solution

  • In your code, each thread creates its own separate mutex, so no relation is enforced between the two. Create a single mutex first, and pass it to the threads.

    I've added to the test print to identify which thread is doing it.

    import time
    import sys
    
    from PyQt5.QtCore import QThread, QMutex
    from PyQt5.QtWidgets import QMainWindow, QApplication
    
    
    class Mainthread(QThread):
        def __init__(self, mutex, parent, suffix=""):
            super().__init__(parent)
            self.parent = parent
            self.running = None
            self.mutex = mutex
            self.suffix = suffix
    
        def run(self):  
            while self.running:
                self.mutex.lock()
                print (f"Test from mainthread{self.suffix}")
                time.sleep(1)
    
                self.mutex.unlock()
    
    
    class MainWindow(QMainWindow):
        def __init__(self):
            super().__init__()
    
            mutex = QMutex()
    
            self.mainthread = Mainthread(mutex, self)
            self.mainthread.running = True
            self.mainthread.start()
    
            self.mainthread1 = Mainthread(mutex, self, "1")
            self.mainthread1.running = True
            self.mainthread1.start()
    
    
    app = QApplication(sys.argv)
    mainwindow = MainWindow()
    mainwindow.show()
    app.exec_()
    

    Note: I don't have PyQt5 installed (and doing so on my architecture is tricky), but I tested this in PySide6 and as far as I know the behavior should be consistent.