TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Writing Multithreaded Applications in C++

74 pointsby StylifyYourBlogover 10 years ago

11 comments

exDM69over 10 years ago
Both of these examples exhibit the &quot;busy waiting&quot; anti pattern where a thread is waiting for something in a loop with a sleep or yield in it. This consumes CPU time, power and resources and may be sleeping more than necessary. The proper fix for this is to wait on a condition variable, which will make sure the thread remains inactive when idle.<p>This may be fine for a trivial example of std::thread and std::mutex but you should almost never do this in practice (there are some exceptions in kernel space when waiting for an I&#x2F;O device).<p>I have a few useful rules of thumb when doing multi threaded programming which I want to share:<p>1) Almost every mutex should be coupled with one or (usually) more condition variables<p>2) A mutex variable named &quot;mutex&quot; is a code smell. Ditto for condition variables named &quot;cond&quot;. They usually have an easy-to-describe function such as &quot;queue_lock&quot;, &quot;not_full&quot; or &quot;not_empty&quot;.
评论 #9014132 未加载
评论 #9013927 未加载
mhogomchunguover 10 years ago
Qt&#x2F;C++ users can now use futures with .then() and .await() constructs through this tasks[1] library.<p>an example of .then() construct is here[2].<p>an example of .await() construct is here[3].What happens here is the following:<p>1. The function is suspected at that line.This suspension does not block the thread and hence the GUI remains responsive. 2. A thread is created and the lambda is run in the new thread. 3. When the lambda completes,the function is unblocked and finish up its work.<p>The above gives easy to read and non blocking synchronous code.<p>[1] <a href="https://github.com/mhogomchungu/tasks" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;mhogomchungu&#x2F;tasks</a><p>[2] <a href="https://github.com/mhogomchungu/zuluCrypt/blob/d0439a4e36521e42fa9392b82dcefd3224d53334/zuluMount-gui/mainwindow.cpp#L812" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;mhogomchungu&#x2F;zuluCrypt&#x2F;blob&#x2F;d0439a4e36521...</a><p>[3] <a href="https://github.com/mhogomchungu/zuluCrypt/blob/eadd2643291f37d8dc96302d854f1ae8e29758d9/zuluCrypt-gui/createkeyfile.cpp#L169" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;mhogomchungu&#x2F;zuluCrypt&#x2F;blob&#x2F;eadd2643291f3...</a>
Animatsover 10 years ago
It&#x27;s nice that C++11 and later have standard wrappers around pthreads. But that doesn&#x27;t make multithreaded programming any easier. Threads still work the same way. All the usual problems, from race conditions to termination, remain. There&#x27;s nothing comparable to Go&#x27;s race detector or Rust&#x27;s compile-time concurrency checking.<p>I&#x27;ve done a fair amount of concurrent programming in C++; I wrote most of the code for a DARPA Grand Challenge off-road autonomous vehicle a decade ago. That was fun. Some of the code is hard real time, and some isn&#x27;t. Thread priorities matter. (This was on QNX, which is a hard real time OS.) There are some unusual techniques; for example, I had a &quot;logprintf&quot; function which was non-blocking. &quot;logprintf&quot; wrote to a queue being written to disk by another thread, and if the queue was full, &quot;...&quot; went into the log. &quot;logprintf&quot; thus could not delay a real-time task and could be used safely in hard real time sections.
评论 #9014958 未加载
Tooover 10 years ago
I&#x27;m curious what guarantees c++ gives on reading variables like the &#x27;data&#x27; in his first example when it can be modified from elsewhere.<p>Yes, the lock will prevent concurrent access but will it prevent the compiler from optimizing away the read completely since main() was the last function that wrote to the variable. I&#x27;ve seen nasty optimization bugs like that happen in C with single threading and strict pointer aliasing and they are not easy to track down.<p>One could interpret his example program like this (unrolled and tweaked a bit).<p><pre><code> int data = 0; &#x2F;&#x2F;ok data is now guaranteed to be equals to 0 thread t(produce, &amp;data); &#x2F;&#x2F;called thread with a pointer to data so if i want to read data again i must invalidate my registers { lock_guard&lt;mutex&gt; lock(theLock); data = 5; &#x2F;&#x2F; i know i set data to 5 here } this_thread::sleep_for(chrono::milliseconds(500)); &#x2F;&#x2F; call contains no references to data, sleep is a &quot;pure&quot; call { lock_guard&lt;mutex&gt; lock(theLock); &#x2F;&#x2F; call contains no references to data if (data == 5) &#x2F;&#x2F; i set data to 5 myself, and i haven&#x27;t done anything that could touch data since then so we optimize away this branch cout &lt;&lt; &quot;data is 5&quot;; } </code></pre> Will the call to lock_guard simply disable all such kind of optimizations? Or are you required to write memory barriers yourself in some way? I guess a simple way to look at it would be that the compiler assumes that thread will keep the pointer to data and that lock_guard has access to that pointer behind the scenes somehow, so that acquiring the mutex &quot;invalidates&quot; your last write, but that would mean acquiring <i>any</i> mutex would invalidate <i>all</i> variables as the mutex doesn&#x27;t specify which data-sets it is locking. Am i thinking correctly? Where can i find more information regarding this.
评论 #9015001 未加载
评论 #9016991 未加载
jarjouraover 10 years ago
I would recommend using std::async instead of std::thread directly as it leaves it up to the STL implementation to manage a thread pool.<p><a href="http://en.cppreference.com/w/cpp/thread/async" rel="nofollow">http:&#x2F;&#x2F;en.cppreference.com&#x2F;w&#x2F;cpp&#x2F;thread&#x2F;async</a>
polskibusover 10 years ago
Le me recommend the Threading Building Blocks library from Intel - it&#x27;s great for writing parallel solutions for data parallelism problems.
vkjvover 10 years ago
Zmq is most often associated with network communications, but its in process sockets are fantastic for multi-threaded programming.
评论 #9014421 未加载
fslothover 10 years ago
Kudos! So elegant. Both C++11 and the article.
robmccollover 10 years ago
OpenMP is still the fastest and easiest way to multithreading in C and C++. Got a for loop with no loop-carried dependencies?<p>#pragma omp parallel for<p>for(...)<p>The Wikipedia page isn&#x27;t a bad starting point: <a href="http://en.m.wikipedia.org/wiki/OpenMP" rel="nofollow">http:&#x2F;&#x2F;en.m.wikipedia.org&#x2F;wiki&#x2F;OpenMP</a>
评论 #9014168 未加载
flipcoderover 10 years ago
Using boost::coroutine, resumable functions are already possible. I&#x27;ve implented an AWAIT() macro in my scheduler and its usage looks like this:<p><a href="https://github.com/flipcoder/kit/blob/master/toys/src/echo.cpp#L25" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;flipcoder&#x2F;kit&#x2F;blob&#x2F;master&#x2F;toys&#x2F;src&#x2F;echo.c...</a><p>Implementation upon boost::coroutine here: <a href="https://github.com/flipcoder/kit/blob/master/include/kit/async/mx.h" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;flipcoder&#x2F;kit&#x2F;blob&#x2F;master&#x2F;include&#x2F;kit&#x2F;asy...</a><p>This is only a proof of concept, but it works.
jokoonover 10 years ago
What&#x27;s the real reason for using threads today ? Why not use multi-process instead ? Or even OpenCL&#x2F;CUDA if one needs to crunch numbers ?<p>The only real use-case for thread I can see right now, is for large game engine that need to process sound, graphics, networking, and inputs, all at the same time. What other type of application does need to make use of threads ?
评论 #9014109 未加载
评论 #9014279 未加载
评论 #9014773 未加载
评论 #9014083 未加载
评论 #9014093 未加载
评论 #9014438 未加载
评论 #9014675 未加载