Qt Multithreading synchronization and communication
1 Multi-thread synchronization
QT offers the following classes to accomplish this: Qmutex, Qmutexlocker, Qsemphore, Qwaitcondition. It may also contain qreadwritelocker, Qreadlocker, Qwritelocker, but
Thread SynchronizationThe application is very few, here only to do simple explanation! The Qmutex, Qmutexlockerqmutex class provides a way to protect a critical section code by allowing only one thread to access the critical section code at a time. The Qmutex::lock () function is used to lock the mutex, and if the mutex is unlocked, the current thread catches and locks it immediately, otherwise the current thread is blocked until the thread holding the mutex is unlocked. When the thread calls the lock () function, it holds the mutex until the unlock () operation is called. Qmutex also provides a trylock () function that returns immediately if the mutex is locked. When the problem comes out, if you want to use mutexes in the Stop () function for mutual exclusion, but the unlock () operation is written there? The unlock () operation has to return again, causing the unlock () operation to never execute ...
QtProvides the Qmutexlocker class how to simplify the processing of mutex, which takes a Qmutex object as a parameter in the constructor and locks it, unlocks the mutex in the destructor.
BOOL Thread::stop ()
{
Qmutexlocker Locker (&mutex);
M_stop = true;
return m_stop;
}
Qreadwritelocker
, Qreadlocker, QwritelockerBelow is a section of the Qreadwritelocker class of objects, read and write the operation of the lock, it is relatively simple, there is no more explanation, see for yourself
MyData data; Qreadwritelock lock; void Readerthread::run () { ... Lock.lockforread (); Access_data_without_modifying_it (&data); Lock.unlock (); ... } void Writerthread::run () { ... Lock.lockforwrite (); Modify_data (&data); Lock.unlock (); ...
Qsemphore
QtThe semaphore is provided by the Qsemaphore class, and the semaphore can be understood as an extension of the mutex function, which can only be locked once and the semaphore can be obtained multiple times, which is used to protect a certain amount of the same resource. The acquire (n) function is used to get n resources, and when there are not enough resources, the caller will be blocked until there are enough available resources. The release (n) function is used to dispose of n resources. The Qsemaphore class also provides a Tryacquire (n) function, in which the function returns immediately if there is not enough resources. A typical semaphore application is in two
ThreadsA certain amount of data (datasize) is passed between the two
ThreadsUse a shared loop cache of a certain size (buffersize).
const int datasize = 100000;
const int buffersize = 4096;
Char Buffer[buffersize];
Producers
ThreadsWrites data to the cache until it reaches the end point, and then begins again at the beginning to overwrite the existing data. Consumers
ThreadsRead the data generated by the former. Producers, consumer instances in the
SyncThere are two requirements, if the producer produces data too quickly, it will overwrite the data that the consumer has not yet read, and if the consumer reads the data too quickly, it will cross the producer and read some junk data. An effective way to solve this problem is to use two semaphores:
Qsemaphore FreeSpace (buffersize);
Qsemaphore usedspace (0);
FreeSpace Semaphore control the producer can populate the cache portion of the data. The Usedspace semaphore controls the areas that consumers can read. The two semaphores are complementary. wherein the FreeSpace semaphore is initialized to buffersize (4096), indicating that at the beginning of the program a buffersize buffer unit can be populated, and the semaphore Usedspace is initialized to 0, indicating that no data is available for reading in the beginning of the program buffer. For this instance, each byte is considered a resource, and the actual application often operates on a larger unit, reducing the overhead associated with using semaphores.
void Producer::run () {for (int i = 0; i < datasize; ++i) { freespace.acquire (); Buffer[i% buffersize] = "MING" [UINT (rand ())% 4]; Usedspace.release (); }
In the producer, we start by acquiring a "free" byte. If the cache is filled with data that the consumer has not yet read, the call to acquire () blocks until the consumer has started consuming the data. Once we have acquired this byte, we populate it with random data ("M", "I", "N" or "G") and release the byte as "used", so it can be used by the consumer thread .
void Consumer::run () {for (int i = 0; i < datasize; ++i) { usedspace.acquire (); Cerr << buffer[i% buffersize]; Freespace.release (); } Cerr << Endl;
int main () { Producer Producer; Consumer Consumer; Producer.start (); Consumer.start (); Producer.wait (); Consumer.wait (); return 0;
qwaitconditionAnother solution to the problem of producers and consumers is to use qwaitcondition, which allows
Thread inWake up other under certain conditions
Threads。 where the Wakeone () function randomly wakes up a wait when the condition is met
Threads, while the Wakeall () function wakes all waits when the condition is met
Threads。
The following overrides the producer and consumer instances to Qmutex as a wait condition, Qwaitcondition allows a
ThreadsUnder certain conditions to wake up other
Threads。
const int datasize = 100000;
const int buffersize = 4096;
Char Buffer[buffersize];
Qwaitcondition Bufferisnotfull;
Qwaitcondition Bufferisnotempty;
Qmutex Mutex;
int usedspace = 0;
Outside of the cache, we declare two qwaitcondition, a Qmutex, and a variable that stores the number of "used" bytes in the cache.
void Producer::run () {for (int i = 0; i < datasize; ++i) { mutex.lock (); if (Usedspace = = buffersize) bufferisnotfull.wait (&mutex); Buffer[i% buffersize] = "MING" [UINT (rand ())% 4]; ++usedspace; Bufferisnotempty.wakeall (); Mutex.unlock (); } }
In the producer, we start by checking whether the cache is full. If it is full, we wait for the "cache is not full" condition. When this condition is met, we write a byte to the cache, increase the usedspace, and wake any wait for this "cache is not blank" condition to become true
Threads。 All statements in the For loop need to be secured with a mutex to protect the atomicity of its operation.
BOOL Wait (Qmutex * Mutex, unsigned long time = Ulong_max);
This function makes the following description, the function unlocks the mutex and waits here, it has two parameters, the first parameter is a locked mutex, the second parameter is the wait time. The wait () function returns immediately if the mutex as the first parameter is in the case that the call is not locked or a recursive lock occurs. Called by the Wait () operation.
ThreadsMakes the mutex as a parameter become locked before the call, and then itself is blocked into a wait state until the following conditions are met: other
ThreadsThe Wakeone () or Wakeall () function is called, in which case a value of "true" is returned. The second parameter time time-out (in milliseconds), the default is Ulong_max, which means that never times out, in which case a value of "false" is returned. The wait () function returns the mutex parameter to a locked state before returning, guaranteeing a principled conversion from the lock state to the wait state.
void Consumer::run () { Forever { mutex.lock (); if (Usedspace = = 0) bufferisnotempty.wait (&mutex); Cerr << buffer[i% buffersize]; --usedspace; Bufferisnotfull.wakeall (); Mutex.unlock (); } Cerr << Endl; }
Consumers do the opposite of producers, he waits for "cache is not blank" condition and wakes up any waiting "cache is not full" condition
Threads。 The main () function is basically the same as above, and this is no longer a lot to say. The static function CurrentThread () in the Qthread class can return the current
ThreadsOf
ThreadsId. In the X11 environment, this ID is a unsigned long type value. Self-summary: Atomic typeQatomicint Qatomicpointer2. Multithreading communication A. The global variable is shared memory B. Pipe C. Signal Slot 3. Multi-process communication signal slot socket file mapping
Qt Multithreading synchronization and communication