crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> Не работает блокировка мьютекса
empirik
  опции профиля:
сообщение 4.2.2014, 21:29
Сообщение #1


Новичок


Группа: Новичок
Сообщений: 2
Регистрация: 18.3.2012
Пользователь №: 3269

Спасибо сказали: 0 раз(а)




Репутация:   0  


Не могу понять, почему несмотря на mutex.lock(), потоки все равно выполняют один и тот же кусок кода одновременно. Есть диалоговое окно, которое по запросу потока должно появляться и позволять пользователю ввести сообщение. Когда сообщение введено и нажата кнопка "ОК", это сообщение должно быть получено этим самым потоком. Вот код:
class MyDialog(QtGui.QDialog):
    got_message = QtCore.pyqtSignal("QString")

    def __init__(self, *args, **kwargs):
        super(MyDialog, self).__init__(*args, **kwargs)

        self.setModal(True)
        self.message_label = QtGui.QLabel(u"Message")
        self.message_input = QtGui.QLineEdit()
        self.dialog_buttons = QtGui.QDialogButtonBox(QtGui.QDialogButtonBox.Ok | QtGui.QDialogButtonBox.Cancel)
        self.dialog_buttons.accepted.connect(self.accept)
        self.dialog_buttons.rejected.connect(self.reject)
        self.dialog_buttons.accepted.connect(self.on_accepted)
        self.hbox = QtGui.QHBoxLayout()
        self.hbox.addWidget(self.message_label)
        self.hbox.addWidget(self.message_input)
        self.vbox = QtGui.QVBoxLayout()
        self.vbox.addLayout(self.hbox)
        self.vbox.addWidget(self.dialog_buttons)
        self.setLayout(self.vbox)

        self.input_finished = QtCore.QWaitCondition()

    @QtCore.pyqtSlot()
    def show_input(self):
        print "showing input"
        self.show()
        self.setModal(True)

    @QtCore.pyqtSlot()
    def on_accepted(self):
        # print "emit: ", self.message_input.text()
        self.got_message.emit(self.message_input.text())
        self.input_finished.wakeAll()

class MyThread(QtCore.QThread):
    mutex = QtCore.QMutex()
    load_message_input = QtCore.pyqtSignal()

    def __init__(self, id, window):
        super(MyThread, self).__init__()
        self.id = id
        self.window = window
        # self.mutex = QtCore.QMutex()

    def run(self):
        print "Thread %d is started" % self.id
        MyThread.mutex.lock()
        self.get_captcha_value()
        print "Thread %d is finishing" % self.id

    def get_captcha_value(self):
        print "Thread %d locks mutex" % self.id
        self.load_message_input.connect(self.window.show_input, QtCore.Qt.BlockingQueuedConnection)
        self.load_message_input.emit()
        self.window.got_message.connect(self.print_message)
        self.window.input_finished.wait(MyThread.mutex)
        print "Thread %d unlocks mutex" % self.id
        MyThread.mutex.unlock()

    @QtCore.pyqtSlot("QString")
    def print_message(self, msg):
        print "Thread %d: %s" % (self.id, msg)


if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)

    window = test_qdialog.MyDialog()
    threads = []

    for i in range(5):
        thread = MyThread(i, window)
        if not thread.isRunning():
            thread.start()
            threads.append(thread)

    sys.exit(app.exec_())


При запуске в консоли получается так:
Thread 0 is startedThread 2 is started

Thread 0 locks mutex
Thread 3 is startedThread 1 is started
Thread 4 is started

showing input
Thread 2 locks mutex
showing input
Thread 3 locks mutex
showing input
Thread 4 locks mutex
showing input
Thread 1 locks mutex
showing input
Thread 0: hello
Thread 2: hello
Thread 3: hello
Thread 4: hello
Thread 1: hello
Thread 0 unlocks mutex
Thread 0 is finishing
Thread 4 unlocks mutex
Thread 4 is finishingThread 3 unlocks mutex

Thread 3 is finishingThread 2 unlocks mutex

Thread 2 is finishing
Thread 1 unlocks mutex
Thread 1 is finishing
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 5.2.2014, 16:49
Сообщение #2


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


я не сильно волоку в питоне, что-то всё таки у меня не укладываются некоторые вещи в голове.
Может всё же мысль была правильной:
self.mutex = QtCore.QMutex()

ну и как следствие удалить атрибут класса
mutex = QtCore.QMutex()

и использовать вместо атрибута класса:
MyThread.mutex.lock()
и
MyThread.mutex.unlock()
атрибут экземпляра:
self.mutex.lock()
и
self.mutex.unlock()



Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
empirik
  опции профиля:
сообщение 5.2.2014, 19:02
Сообщение #3


Новичок


Группа: Новичок
Сообщений: 2
Регистрация: 18.3.2012
Пользователь №: 3269

Спасибо сказали: 0 раз(а)




Репутация:   0  


Цитата(Litkevich Yuriy @ 5.2.2014, 17:49) *
я не сильно волоку в питоне, что-то всё таки у меня не укладываются некоторые вещи в голове.
Может всё же мысль была правильной:
self.mutex = QtCore.QMutex()

ну и как следствие удалить атрибут класса
mutex = QtCore.QMutex()

и использовать вместо атрибута класса:
MyThread.mutex.lock()
и
MyThread.mutex.unlock()
атрибут экземпляра:
self.mutex.lock()
и
self.mutex.unlock()


Не, если делать так, то мьютекс не будет разделяемым, у каждого потока он будет свой, насколько я понимаю. И тогда каждый что хочет, то и делает. А в данном случае - все потоки обращаются к одному мьютексу.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Iron Bug
  опции профиля:
сообщение 6.2.2014, 12:00
Сообщение #4


Профессионал
*****

Группа: Модератор
Сообщений: 1611
Регистрация: 6.2.2009
Из: Yekaterinburg
Пользователь №: 533

Спасибо сказали: 219 раз(а)




Репутация:   12  


я не программист на питоне, но сдаётся мне, что он у каждого потока создаёт собственный мьютекс и эти разные мьютексы потом лочатся независимо друг от друга.

Сообщение отредактировал Iron Bug - 6.2.2014, 12:00
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 29.3.2024, 15:02