summaryrefslogtreecommitdiffstats
path: root/src/corelib/doc
diff options
context:
space:
mode:
authorSze Howe Koh <szehowe.koh@gmail.com>2013-10-02 23:59:17 +0800
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-10-06 01:08:58 +0200
commitdc6852ca63ab56eddb8a8843b0c383d51a4020a9 (patch)
tree123d3d1c7b6855cd7ff42669ee30345e2f923fed /src/corelib/doc
parent370b64209256b1b5624a568e208d4e2bb6ce99c2 (diff)
Doc: Expand on thread synchronization details
- Introduce the concept of "mutual exclusion" - Rewrite/add explanations on how synchronization happens and how to use these tools - Remove similar content from the "Thread Basics" page - Fix links to examples Change-Id: Id008a8fc3f68bf242cae1704c5c8318149d908b4 Reviewed-by: Olivier Goffart <ogoffart@woboq.com> Reviewed-by: Jerome Pasion <jerome.pasion@digia.com>
Diffstat (limited to 'src/corelib/doc')
-rw-r--r--src/corelib/doc/src/threads-basics.qdoc26
-rw-r--r--src/corelib/doc/src/threads.qdoc74
2 files changed, 43 insertions, 57 deletions
diff --git a/src/corelib/doc/src/threads-basics.qdoc b/src/corelib/doc/src/threads-basics.qdoc
index 8b690c15ae..e511c10423 100644
--- a/src/corelib/doc/src/threads-basics.qdoc
+++ b/src/corelib/doc/src/threads-basics.qdoc
@@ -224,27 +224,11 @@
has terminated.
\endlist
- \section2 Using a Mutex to Protect the Integrity of Data
-
- A mutex is an object that has \l{QMutex::}{lock()} and \l{QMutex::}{unlock()}
- methods and remembers if it is already locked. A mutex is designed to be
- called from multiple threads. \l{QMutex::}{lock()} returns immediately if
- the mutex is not locked. The next call from another thread will find the
- mutex in a locked state and then \l{QMutex::}{lock()} will block the thread
- until the other thread calls \l{QMutex::}{unlock()}. This functionality can
- make sure that a code section will be executed by only one thread at a time.
-
- The following line sketches how a mutex can be used to make a method
- thread-safe:
-
- \code
- void Worker::work()
- {
- this->mutex.lock(); // first thread can pass, other threads will be blocked here
- doWork();
- this->mutex.unlock();
- }
- \endcode
+ \section2 Protecting the Integrity of Data
+
+ When writing a multithread application, extra care must be taken to avoid
+ data corruption. See \l{Synchronizing Threads} for a discussion on how to
+ use threads safely.
\section2 Dealing with Asynchronous Execution
diff --git a/src/corelib/doc/src/threads.qdoc b/src/corelib/doc/src/threads.qdoc
index 2726ea1709..a1967ff16b 100644
--- a/src/corelib/doc/src/threads.qdoc
+++ b/src/corelib/doc/src/threads.qdoc
@@ -290,51 +290,46 @@
\contentspage Thread Support in Qt
\nextpage Reentrancy and Thread-Safety
- While the main idea
- with threads is that they should be as concurrent as possible,
- there are points where threads must stop and wait for other
- threads. For example, if two threads try to access the same
- global variable simultaneously, the results are usually
- undefined.
+ While the purpose of threads is to allow code to run in parallel,
+ there are times where threads must stop and wait for other
+ threads. For example, if two threads try to write to the same
+ variable simultaneously, the result is undefined. The principle of
+ forcing threads to wait for one another is called \e{mutual exclusion}.
+ It is a common technique for protecting shared resources such as data.
Qt provides low-level primitives as well as high-level mechanisms
for synchronizing threads.
\section1 Low-Level Synchronization Primitives
- QMutex provides a mutually exclusive lock, or mutex. At most one
- thread can hold the mutex at any time. If a thread tries to
- acquire the mutex while the mutex is already locked, the thread will
- be put to sleep until the thread that currently holds the mutex
- unlocks it. Mutexes are often used to protect accesses to shared
- data (i.e., data that can be accessed from multiple threads
- simultaneously). In the \l{Reentrancy and Thread-Safety} section
- below, we will use it to make a class thread-safe.
+ QMutex is the basic class for enforcing mutual exclusion. A thread
+ locks a mutex in order to gain access to a shared resource. If a second
+ thread tries to lock the mutex while it is already locked, the second
+ thread will be put to sleep until the first thread completes its task
+ and unlocks the mutex.
QReadWriteLock is similar to QMutex, except that it distinguishes
- between "read" and "write" access to shared data and allows
- multiple readers to access the data simultaneously. Using
- QReadWriteLock instead of QMutex when it is possible can make
- multithreaded programs more concurrent.
+ between "read" and "write" access. When a piece of data is not being
+ written to, it is safe for multiple threads to read from it simultaneously.
+ A QMutex forces multiple readers to take turns to read shared data, but a
+ QReadWriteLock allows simultaneous reading, thus improving parallelism.
QSemaphore is a generalization of QMutex that protects a certain
- number of identical resources. In contrast, a mutex protects
- exactly one resource. The \l{threads/semaphores}{Semaphores}
- example shows a typical application of semaphores: synchronizing
- access to a circular buffer between a producer and a consumer.
-
- QWaitCondition allows a thread to wake up other threads when some
- condition has been met. One or many threads can block waiting for
- a QWaitCondition to set a condition with
- \l{QWaitCondition::wakeOne()}{wakeOne()} or
- \l{QWaitCondition::wakeAll()}{wakeAll()}. Use
- \l{QWaitCondition::wakeOne()}{wakeOne()} to wake one randomly
- selected event or \l{QWaitCondition::wakeAll()}{wakeAll()} to
- wake them all. The \l{threads/waitconditions}{Wait Conditions}
- example shows how to solve the producer-consumer problem using
- QWaitCondition instead of QSemaphore.
-
- Note that Qt's synchronization classes rely on the use of properly
+ number of identical resources. In contrast, a QMutex protects
+ exactly one resource. The \l{Semaphores Example} shows a typical application
+ of semaphores: synchronizing access to a circular buffer between a producer
+ and a consumer.
+
+ QWaitCondition synchronizes threads not by enforcing mutual exclusion but by
+ providing a \e{condition variable}. While the other primitives make threads
+ wait until a resource is unlocked, QWaitCondition makes threads wait until a
+ particular condition has been met. To allow the waiting threads to proceed,
+ call \l{QWaitCondition::wakeOne()}{wakeOne()} to wake one randomly
+ selected thread or \l{QWaitCondition::wakeAll()}{wakeAll()} to wake them all
+ simultaneously. The \l{Wait Conditions Example} shows how to solve the
+ producer-consumer problem using QWaitCondition instead of QSemaphore.
+
+ \note Qt's synchronization classes rely on the use of properly
aligned pointers. For instance, you cannot use packed classes with
MSVC.
@@ -381,7 +376,14 @@
system and runs the method immediately in the current thread.
There is no risk of deadlocks when using the event system for thread
- synchronization, unlike using low-level primitives.
+ synchronization, unlike using low-level primitives. However, the event system
+ does not enforce mutual exclusion. If invokable methods access shared data,
+ they must still be protected with low-level primitives.
+
+ Having said that, Qt's event system, along with \l{Implicit Sharing}{implicitly
+ shared} data structures, offers an alternative to traditional thread locking.
+ If signals and slots are used exclusively and no variables are shared between
+ threads, a multithreaded program can do without low-level primitives altogether.
\sa QThread::exec(), {Threads and QObjects}
*/