The Qmutex class provides a sequential access between threads.
The purpose of Qmutex is to protect an object, data structure, or code snippet, so that only one thread can access it at the same time. (in Java terminology, it is similar to the Sync keyword "synchronized"). For example, here's a way to print two messages to the user:
[CPP]View PlainCopy
- void SomeMethod ()
- {
- Qdebug ("Hello");
- Qdebug ("World");
- }
If this method is called in two threads at the same time, the order of the results will be:
Hello Hello world
If you are using a mutex:
[CPP]View PlainCopy
- Qmutex Mutex;
- void SomeMethod ()
- {
- Mutex.lock ();
- Qdebug ("Hello");
- Qdebug ("World");
- Mutex.unlock ();
- }
In Java terminology, this code should be:
[CPP]View PlainCopy
- void SomeMethod ()
- {
- Synchronized {
- Qdebug ("Hello");
- Qdebug ("World");
- }
- }
Then only one thread at a time can run SomeMethod and the order of the messages is always correct. This is, of course, a very simple example, but it applies to anything that needs to happen at a specific frequency.
But you call lock () in one thread, and the other thread will attempt to call Lock () at the same location to block, knowing that the other thread will get the lock after the thread calls unlock (). A non-blocking selection of lock () is Trylock ().
Experimental section:
Scenario One:
[CPP]View PlainCopy
- #include <QtCore/QCoreApplication>
- #include <Qthread>
- #include <QTextStream>
- Class Mythreada: Public qthread {
- Public
- Virtual void run ();
- };
- Class mythreadb: Public qthread {
- Public
- Virtual void run ();
- };
- int number=6;
- void Mythreada::run () {
- Number *= 5;
- Number/= 4;
- }
- void Mythreadb::run () {
- Number *= 3;
- Number/= 2;
- }
- int main (int argc, char *argv[])
- {
- Qcoreapplication app (argc, argv);
- Mythreada A;
- MYTHREADB b;
- A.run ();
- B.run ();
- A.terminate ();
- B.terminate ();
- Qtextstream out (stdout);
- out<<number;
- return App.exec ();
- }
The above code, very simple, wrote two threads, covering the Qthread pure virtual function run (), the two refactoring of the Run method is the global variable number operation,
The two methods are called sequentially in the main function, and after A.run () is executed, number is 7,b.run () after 10.
Scenario Two:
[CPP]View PlainCopy
- #include <QtCore/QCoreApplication>
- #include <Qthread>
- #include <QTextStream>
- Class Mythreada: Public qthread {
- Public
- Virtual void run ();
- };
- Class mythreadb: Public qthread {
- Public
- Virtual void run ();
- };
- int number=6;
- void Mythreada::run () {
- Number *= 5;
- Sleep (1);
- Number/= 4;
- }
- void Mythreadb::run () {
- Number *= 3;
- Sleep (1);
- Number/= 2;
- }
- int main (int argc, char *argv[])
- {
- Qcoreapplication app (argc, argv);
- Mythreada A;
- MYTHREADB b;
- A.start ();
- B.start ();
- A.wait ();
- B.wait ();
- Qtextstream out (stdout);
- out<<number;
- return App.exec ();
- }
Operation Result:
number=11;
Using the Qthread method Start () is the same as opening two threads, it is worth noting that the wait () function, can not wait for itself, this is used to interact with multiple threads, so can not be used as sleep (). This function blocks the main thread when it is called in the main thread. If you want to let the child thread pause externally, the best way is to set a flag in the child thread, change the flag in the main thread, and judge in the run function of the child thread, by calling its protection function sleep () to achieve the purpose of the pause.
To view the source code, you have a clear concept:
[CPP]View PlainCopy
- BOOL Qthread::wait (unsigned long time)
- {
- Q_d (Qthread);
- Qmutexlocker Locker (&d->mutex);
- if (D->id = = GetCurrentThreadID ()) {
- Qwarning ("Qthread::wait:thread tried to wait on itself"); //When it is itself, return false directly
- return false;
- }
- if (d->finished | |!d->running) //The thread associated with this thread object has ended execution (for example, returned from the Run function). Returns true if the thread ends. Returns true if the thread has not started yet.
- return true;
- ++d->waiters;
- Locker.mutex ()->unlock ();
- BOOL ret = false;
- switch (WaitForSingleObject (D->handle, Time)) { //Call Win's object handler function
- Case WAIT_OBJECT_0: //Core object is activated, waiting for success
- ret = true;
- Break ;
- Case wait_failed:
- Qerrnowarning ("Qthread::wait:thread wait Failure");
- Break ;
- Case wait_abandoned:
- Case Wait_timeout:
- Default:
- Break ;
- }
- Locker.mutex ()->lock ();
- --d->waiters;
- if (ret &&!d->finished) { //Although the response was successful, but the associated object did not end execution
- //thread was terminated by someone else
- d->terminated = true;
- Qthreadprivate::finish (This, false);
- }
- if (d->finished &&!d->waiters) { //The associated object execution ends and the wait number is zero, the handle is closed.
- CloseHandle (D->handle);
- D->handle = 0;
- }
- return ret;
- }
Scenario Three: (Mutex effect)
[CPP]View PlainCopy
- #include <QtCore/QCoreApplication>
- #include <Qthread>
- #include <QTextStream>
- #include <QMutex>
- Class Mythreada: Public qthread {
- Public
- Virtual void run ();
- };
- Class mythreadb: Public qthread {
- Public
- Virtual void run ();
- };
- Qmutex Mutex;
- int number=6;
- void Mythreada::run () {
- Mutex.lock ();
- Number *= 5;
- Sleep (1);
- Number/= 4;
- Mutex.unlock ();
- }
- void Mythreadb::run () {
- Mutex.lock ();
- Number *= 3;
- Sleep (1);
- Number/= 2;
- Mutex.unlock ();
- }
- int main (int argc, char *argv[])
- {
- Qcoreapplication app (argc, argv);
- Mythreada A;
- MYTHREADB b;
- A.start ();
- B.start ();
- A.wait ();
- B.wait ();
- Qtextstream out (stdout);
- out<<number;
- return App.exec ();
- }
Operation Result:
number=10;
The experimental results show that QMUTEX protects the global variables, and only one thread can access it at the same time.
Only one mention is the use of Trylock (), if the above code is changed to Mutex.trylock (), then the execution result may be 11, because it is trying to lock the mutex. If the lock is obtained, the function returns True. If the mutex is already locked by another process, the function returns false instead of waiting until the lock is available.
and cannot add the sleep () function, otherwise prompt "A mutex must be unlocked in the same thread that locked it." Run error.
http://blog.csdn.net/mznewfacer/article/details/6966752
Summary of QT multithreading programming (ii)--qmutex