SlideShare a Scribd company logo
1 of 31
Essentials of MultithreadedSystem Programming in C++ Shuo Chen 2011/02 blog.csdn.net/Solstice giantchen@gmail.com @bnu_chenshuo
Contents Challenges in multithreaded system programming Thread safety of C and C++ libraries RAII and fork() fork() and signal handling in multithreaded programs 2011/02 Shuo Chen (blog.csdn.net/Solstice) 2
Audience: C++ programmers Familiar with Pthreads and Sockets API Knows thread safety, deadlock, race condition, etc. In a word: read through APUE2e and UNP3e (vol. 1) by W. Richard Stevens et al. All discussions are based on Linux 2.6.x, x >= 28 There are new syscalls, egsignalfd, eventfd, and timerfd x86 and x64 platforms 2011/02 Shuo Chen (blog.csdn.net/Solstice) 3
Multi-threaded system programming Multithreading is inevitable in this multi-core era The difficulties are not learning synchronization primitives (mutexes, condition variables) ~10 functions are sufficient to do it right But understanding interactions between existing system calls and library functions Understands how threads affect system design Use it wisely and effectively Avoid common pitfalls and fallacies 2011/02 Shuo Chen (blog.csdn.net/Solstice) 4
11 essential Pthreads functions 11 out of 110+ pthreads functions 2 -> create and join threads 4 -> init/destroy, lock/unlock mutexes 5 -> init/destroy, wait/signal/broadcast condvars Think twice if you need more Some are okay, eg. once and key, maybe rwlock Some are bad, eg. cancel and kill, semaphores Check muduo/base for encapsulation in C++ http://code.google.com/p/muduo http://github.com/chenshuo/recipes   click  thread 2011/02 Shuo Chen (blog.csdn.net/Solstice) 5
An asynchronous world Never assume the sequence of events without proper synchronization. Knows happens-before relation, memory visibility, etc. The effect of an interaction between two [thread]s must be independent of the speed at which it is carried out. --- Brinch Hansen 1973 2011/02 Shuo Chen (blog.csdn.net/Solstice) 6
Standards and practices Although the latest official standards of C and C++ languages (C99 and C++03) do not say a word about process or thread We write multi-process and/or multi-threaded C/C++ programs in real life, as a real-world need We can’t wait it to be standardized, as standards usually fall behind practices for years btw, if there are not real life multi-threads programs , how do people what/how to standardize? We adhere to some de facto standards A lot simpler if we focus on one hardware and one OS 2011/02 Shuo Chen (blog.csdn.net/Solstice) 7
Thread identifier on Linux Use pid_t as thread id, instead of pthread_t, on Linux pthread_tthid = pthread_self(), thid is opaque (uintptr_t) pid_ttid = ::gettid(), tid is task id, usually a small integer /proc/tid/, /proc/pid/task/tid/, ps, top all work fine How to implement gettid() efficiently? Thread local? gettid(2) is a syscall, but the output should never change getpid(2) caches the result, should gettid() do the same? What if fork(), will it caches the old value in child proc? How about pthread_atfork() to clear it up? Check muduo/base/Thread.cc for details 2011/02 Shuo Chen (blog.csdn.net/Solstice) 8
Creation of threads A library should not create its own ‘background’ thread  without prior informed consent Makes a program non-forkable Never create thread before main() Avoid creating thread in ctor of static or global object Breaks static objects constructing, eg. protobuf registering The number of threads created should be independentof system load, eg. # of connections, # of requests otherwise non-scalable Reuse threads, by assign multiple roles to it Doing IO and timer with muduoEventLoop class For simple task, do it within IO callbacks in IO threads 2011/02 Shuo Chen (blog.csdn.net/Solstice) 9
Three ways of termination http://blog.csdn.net/program_think/archive/2009/03/14/3991107.aspx Natural death – return from thread function, good Suicide – call pthread_exit() Mudered – killed by pthread_cancel() Rule: let it die, never suicide or murder a thread Why? inherently deadlock-prone: no chance to unlock Design your program so that a thread can be waken up and safely exits For reference Java Thread.{stop, suspend and destroy} are deprecated Boost Threads doesn’t provide thread::cancel() 2011/02 Shuo Chen (blog.csdn.net/Solstice) 10
pthread_cancel() and C++ In C, we have concept of ‘cancellation point’ In C++, pthread_cancel() throws an exception in that thread, helps unwinding objects on stack The exception must reach the outmost function, otherwise core dump: FATAL: exception not rethrown Aborted (core dumped) Always rethrow in catch(…) cause Ulrich Drepper “Cancellation and C++ Exceptions” Better: never cancel or kill a thread 2011/02 Shuo Chen (blog.csdn.net/Solstice) 11
exit() is not thread safe in C++ exit() destructs static or global objects, (_exit() doesn’t) The destructor may try to hold a lock The caller  function may have held the same lock already End up in a dead lock Check following code for an example of dead lock  github.com/chenshuo/recipes/blob/master/thread/test/ExitDeadLock.cc How to quit a multi-threaded program safely? An irregular but simple solution: make a process killable, eg. p.29  blog.csdn.net/Solstice/archive/2010/10/19/5950190.aspx It’s not fault of exit(), but static or global objects Try to avoid static or global objects in C++, except for PODs 2011/02 Shuo Chen (blog.csdn.net/Solstice) 12
Thread local __thread in g++ Thread safe by natural, unless escaped to other thread More efficient implementation,  than pthread_key_t See “ELF Handling For Thread-Local Storage” In C++, must be initialized with constant-expression No 	__thread string t_obj("Chen Shuo"); No 	__thread string* t_obj = new string; Only 	__thread string* t_obj = NULL; More rules:  http://gcc.gnu.org/onlinedocs/gcc/Thread_002dLocal.html Use pthread_key_t if you want auto destruction 2011/02 Shuo Chen (blog.csdn.net/Solstice) 13
Use non-recursive mutex only A basic assumption of holding a mutex Once I lock it, I can modify the guarded object safely Which is not true for recursive mutex, eg. http://blog.csdn.net/Solstice/archive/2010/02/12/5307710.aspx#_Toc11928 Recursive mutexes by David Butenhof http://zaval.org/resources/library/butenhof1.html  Recursive locks - a blessing or a curse?   http://www.thinkingparallel.com/2006/09/27/recursive-locks-a-blessing-or-a-curse/ 2011/02 Shuo Chen (blog.csdn.net/Solstice) 14
Impacts of introducing threads Threading is a late patch to OS kernel Unix kernel and API formed in early 1970s First implementation of threads emerged in early 1990s Breaks lots of assumptions made during the 20 years Library functions with side effects must be revisited malloc/free, fread/fseekcan be made thread-safe with locks Functions that return or use static allocated space are not thread safe but may have thread-safe variants asctime_r, ctime_r, gmtime_r, rand_r, stderror_r, strtok_r errno is not an ‘extern int’, but a per-thread value extern int *__errno_location(void); #define errno (*__errno_location()) 2011/02 Shuo Chen (blog.csdn.net/Solstice) 15
Thread safety of C library Individual system calls must be thread safe Be caution of interfering of same file descriptor from multiple threads Most of glibc library functions are thread safe nowadays Counterintuitively, Posix standards lists functions thatare not required to be thread safe, it's a black list. http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_09 2.9.1 Thread-Safety : All functions defined by this volume of POSIX.1-2008 shall be thread-safe, except that the following functions need not be thread-safe. Notably, getenv/putenv/setenv/system() are not safe 2011/02 Shuo Chen (blog.csdn.net/Solstice) 16
FILE* functions are thread safe Read ‘man flockfile’, but they are not composable, eg. fseek(), followed by fread() The file position may change during the course by a different thread Wrap with flockfile(FILE*) and funlockfile(FILE*)  Same applies to lseek(2) and read(2), but how to lock? Use pread(2) instead, which doesn’t change the file offset In general, a function that calls two thread-safe functions is not guaranteed to be thread-safe Just like exception-safety, thread-safety is not composable 2011/02 Shuo Chen (blog.csdn.net/Solstice) 17
Thread safety is not composable A solution works in single-threaded program may not apply to multi-threaded program. Any solution calls two or more thread safe function are not necessarily correct in multi-threaded program What’s the time in London now? Program runs in New York string oldTz = getenv("TZ");             // save TZ putenv("TZ=Europe/London"); tzset();     // set TZ to London struct tm localTimeInLN = *localtime(time(NULL)); setenv("TZ", oldTz.c_str(), 1); tzset(); // restore old TZ This code impacts localtime() in other threads Thread safe functions are not composable unless you carefully design the interface and interactions 2011/02 Shuo Chen (blog.csdn.net/Solstice) 18
Thread safety of C++ std library Although not required by the standard, the de facto says Unshared objects are independent: Two threads can freely use different objects without any special action on the caller's part. We call it "same level as built-in types." This applies to STL containers like map, vector, string Pure functions are safe, eg. Most of STL algorithms. The global cin/cout objects are shared by threads, and are not thread safe. Moreover, they can't be made safe cout << a << b;  cout.operator<<(a).operator<<(b); Two function calls can be interrupted by another thread Use printf(3) instead, it's thread safe and atomic. Allocators must be thread safe, as they are shared 2011/02 Shuo Chen (blog.csdn.net/Solstice) 19
Thread-Safe vs. Thread-Efficient printf(3) and malloc(3) are thread safe, but not necessarily efficient enough, esp. on multi-cores printf(3) locks FILE* stdout, synchronizes threads not good for multi-threaded logging, we need a better lib your default malloc(3) may not optimized for multi-threads and multi-cores it may lock global heap for each allocation try tcmalloc, Google's thread-cache malloc see Intel. Is your memory management multi-core ready? http://software.intel.com/en-us/blogs/2009/08/21/is-your-memory-management-multi-core-ready/ 2011/02 Shuo Chen (blog.csdn.net/Solstice) 20
Operate one fd in one thread Although system calls of file descriptors are safe What if a thread close a fd when other thread is block reading it? What happens if a thread add a fd to epoll watch list while other thread is epoll_wait()ing it? What happens if two threads poll same fd, and find it readable simultaneously? What if two threads read the same TCP socket but each get partial data? How do you tell which part comes first? Rule: all operations on one file descriptor should happen in one thread, make your life a lot easier 2011/02 Shuo Chen (blog.csdn.net/Solstice) 21
File descriptors in threads File descriptors are small integers, unlike HANDLE When create a new fd, kernel picks the lowest unused one Higher possibility of cross-talk, if careless, eg. A fd shared by two threads The first thread have just close()d it The second is about to read() it But a third thread happened to create a new fd with same id (the lowest available int reused) during the period What does the second thread read from? Any other impact? Solution: manage resource with RAII idiom And use the usual technique to manage object life cycles 2011/02 Shuo Chen (blog.csdn.net/Solstice) 22
C++ and fork() A object could construct once but destruct twice int main() { Foofoo; // call 'Foo::Foo'   fork();  // fork to two process // call 'Foo::~Foo' in parent *and* child processes } It might be a problem, if Foo owns some resource that is not inherited by child process Again, avoid static or global objects in C++ In child process, the object may not be properly  initialized A global muduo::Timestamp startTime(now()) is wrong 2011/02 Shuo Chen (blog.csdn.net/Solstice) 23
RAII and fork() fork() doesn't copy all state Open file descriptors are inherited by child process But the offset of file are independent The child does not inherit its parent's memory locks (mlock(2), mlockall(2)) record locks from its parent (fcntl(2)) timers from its parent (setitimer(2), alarm(2), timer_create(2)), and others So the RAII idiom may not work well in fork()ed process A RAII class that wraps timer_create/timer_delete in ctor/dtor may fail in child process after fork() Use pthread_atfork() as the last resort 2011/02 Shuo Chen (blog.csdn.net/Solstice) 24
C++ and threads Use scoped lock guard only, check muduo/base/Mutex.h Don't allow exceptions to propagate across module boundaries don't let exception propagate out of the thread main function, catch all exceptions in the outer-most function But, rethrow the one of pthread_cancel(), as we said before Don't allow exceptions to propagate out of your callback, esp. callbacks from C library, eg. the init_routine registered to pthread_once() Better: don't use exception in C++ 2011/02 Shuo Chen (blog.csdn.net/Solstice) 25
Threads and fork() The fork() model doesn’t fit well in threads A fundamental flaw of PosixOSes, as other threads disappear in child, the state is not consistent in child proc After fork a multi-threaded program you may only call async-signal-safe functions in child, as if in signal handler malloc() is not safe, other thread may hold the lock when fork()ing, and no chance to unlock in the new process So does printf(), pthread_* and others. The only safe way to use fork() in a multi-threaded program is calling exec() immediately in child process And make sure set close-on-exec flag on every file descriptors in parent process for security reasons. 2011/02 Shuo Chen (blog.csdn.net/Solstice) 26
Signals and threads The whole Posix signal mechanism is a shit Only async-signal-safe functions can be called in signal handler, also called 'reentrant functions' Most of the functions are notasync-signal-safe, except those listed in Posix standards, so it's a white list http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03_03 'man 7 signal' to get the list on Linux  None of pthread_* are not async-signal-safe, you can't notify a condvar or lock a mutex in signal handler Surprisely, gettimeofday(2) is not async-signal-safe 2011/02 Shuo Chen (blog.csdn.net/Solstice) 27
Deal with signals in MT programs Rule 1: do not use signal don't use it as IPC, eg. SIGUSR1, SIGUSR2, SIGINT, SIGHUP don't use library functions built upon signals, eg. alarm, sleep, usleep, timer_create, etc. Rule 2: when you absolutely need, convert an async signal  to synchronous file descriptor readable event use signalfd in high Linux kernel version Normally,  the set of signals to be received via the file descriptor should be blocked using pthread_sigmask(3), to prevent the signals being handled according to their default dispositions. or open a pipe(2), write(2) one byte in signal handler, and read(2) or poll(2) it in main thread 2011/02 Shuo Chen (blog.csdn.net/Solstice) 28
Other resources http://pubs.opengroup.org/onlinepubs/9699919799/ http://www.linuxprogrammingblog.com/threads-and-fork-think-twice-before-using-them http://www.linuxprogrammingblog.com/all-about-linux-signals http://www.cppblog.com/lymons/archive/2008/06/01/51838.html Seven posts in http://www.cppblog.com/lymons/category/9446.html 2011/02 Shuo Chen (blog.csdn.net/Solstice) 29
To be continued Essential of non-blocking network programming in C++ Birth of a reactor – design and implementation of Muduo 2011/02 Shuo Chen (blog.csdn.net/Solstice) 30
Avoid static or global objects Except for PODs 2011/02 Shuo Chen (blog.csdn.net/Solstice) 31

More Related Content

What's hot

What's hot (20)

Introduction to Kotlin coroutines
Introduction to Kotlin coroutinesIntroduction to Kotlin coroutines
Introduction to Kotlin coroutines
 
C multiple choice questions and answers pdf
C multiple choice questions and answers pdfC multiple choice questions and answers pdf
C multiple choice questions and answers pdf
 
Overriding
OverridingOverriding
Overriding
 
Asynchronous JavaScript Programming with Callbacks & Promises
Asynchronous JavaScript Programming with Callbacks & PromisesAsynchronous JavaScript Programming with Callbacks & Promises
Asynchronous JavaScript Programming with Callbacks & Promises
 
Function in C
Function in CFunction in C
Function in C
 
From Generator to Fiber the Road to Coroutine in PHP
From Generator to Fiber the Road to Coroutine in PHPFrom Generator to Fiber the Road to Coroutine in PHP
From Generator to Fiber the Road to Coroutine in PHP
 
In-depth analysis of Kotlin Flows
In-depth analysis of Kotlin FlowsIn-depth analysis of Kotlin Flows
In-depth analysis of Kotlin Flows
 
Monadic Java
Monadic JavaMonadic Java
Monadic Java
 
Golang Channels
Golang ChannelsGolang Channels
Golang Channels
 
clean code book summary - uncle bob - English version
clean code book summary - uncle bob - English versionclean code book summary - uncle bob - English version
clean code book summary - uncle bob - English version
 
Coroutines in Kotlin
Coroutines in KotlinCoroutines in Kotlin
Coroutines in Kotlin
 
C# conventions & good practices
C# conventions & good practicesC# conventions & good practices
C# conventions & good practices
 
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
Nat, List and Option Monoids -from scratch -Combining and Folding -an exampleNat, List and Option Monoids -from scratch -Combining and Folding -an example
Nat, List and Option Monoids - from scratch - Combining and Folding - an example
 
Control Structure in C
Control Structure in CControl Structure in C
Control Structure in C
 
Why rust?
Why rust?Why rust?
Why rust?
 
Introduction to kotlin coroutines
Introduction to kotlin coroutinesIntroduction to kotlin coroutines
Introduction to kotlin coroutines
 
Compilers: Principles, Techniques, and Tools 2nd By Alfred V. Aho (Internatio...
Compilers: Principles, Techniques, and Tools 2nd By Alfred V. Aho (Internatio...Compilers: Principles, Techniques, and Tools 2nd By Alfred V. Aho (Internatio...
Compilers: Principles, Techniques, and Tools 2nd By Alfred V. Aho (Internatio...
 
Trees In The Database - Advanced data structures
Trees In The Database - Advanced data structuresTrees In The Database - Advanced data structures
Trees In The Database - Advanced data structures
 
Code Smells
Code SmellsCode Smells
Code Smells
 
Quill vs Slick Smackdown
Quill vs Slick SmackdownQuill vs Slick Smackdown
Quill vs Slick Smackdown
 

Viewers also liked

Efficient logging in multithreaded C++ server
Efficient logging in multithreaded C++ serverEfficient logging in multithreaded C++ server
Efficient logging in multithreaded C++ server
Shuo Chen
 
Database, concetti di base
Database, concetti di baseDatabase, concetti di base
Database, concetti di base
antmng
 
Datetime - Julian Date
Datetime - Julian DateDatetime - Julian Date
Datetime - Julian Date
Shuo Chen
 
Galvin-operating System(Ch8)
Galvin-operating System(Ch8)Galvin-operating System(Ch8)
Galvin-operating System(Ch8)
dsuyal1
 
Lecture5
Lecture5Lecture5
Lecture5
jntu
 

Viewers also liked (20)

PThreads Vs Win32 Threads
PThreads  Vs  Win32 ThreadsPThreads  Vs  Win32 Threads
PThreads Vs Win32 Threads
 
Where destructors meet threads
Where destructors meet threadsWhere destructors meet threads
Where destructors meet threads
 
Concordion java
Concordion javaConcordion java
Concordion java
 
Tutorial windows service with java (procrun)
Tutorial windows service with java (procrun)Tutorial windows service with java (procrun)
Tutorial windows service with java (procrun)
 
Fork Yeah! The Rise and Development of illumos
Fork Yeah! The Rise and Development of illumosFork Yeah! The Rise and Development of illumos
Fork Yeah! The Rise and Development of illumos
 
Zurg part 1
Zurg part 1Zurg part 1
Zurg part 1
 
Efficient logging in multithreaded C++ server
Efficient logging in multithreaded C++ serverEfficient logging in multithreaded C++ server
Efficient logging in multithreaded C++ server
 
Multithreading Presentation
Multithreading PresentationMultithreading Presentation
Multithreading Presentation
 
Database - progettazione
Database - progettazioneDatabase - progettazione
Database - progettazione
 
Database, concetti di base
Database, concetti di baseDatabase, concetti di base
Database, concetti di base
 
Datetime - Julian Date
Datetime - Julian DateDatetime - Julian Date
Datetime - Julian Date
 
Database introduzione
Database introduzioneDatabase introduzione
Database introduzione
 
Deadlock
DeadlockDeadlock
Deadlock
 
Java Threading
Java ThreadingJava Threading
Java Threading
 
thread-clustering
thread-clusteringthread-clustering
thread-clustering
 
Galvin-operating System(Ch8)
Galvin-operating System(Ch8)Galvin-operating System(Ch8)
Galvin-operating System(Ch8)
 
Ch05
Ch05Ch05
Ch05
 
Threading
ThreadingThreading
Threading
 
Lecture5
Lecture5Lecture5
Lecture5
 
C++ Actor Model - You’ve Got Mail ...
C++ Actor Model - You’ve Got Mail ...C++ Actor Model - You’ve Got Mail ...
C++ Actor Model - You’ve Got Mail ...
 

Similar to Essentials of Multithreaded System Programming in C++

Medical Image Processing Strategies for multi-core CPUs
Medical Image Processing Strategies for multi-core CPUsMedical Image Processing Strategies for multi-core CPUs
Medical Image Processing Strategies for multi-core CPUs
Daniel Blezek
 
Threaded Programming
Threaded ProgrammingThreaded Programming
Threaded Programming
Sri Prasanna
 
Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016
Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016
Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016
Christian Schneider
 
Track c-High speed transaction-based hw-sw coverification -eve
Track c-High speed transaction-based hw-sw coverification -eveTrack c-High speed transaction-based hw-sw coverification -eve
Track c-High speed transaction-based hw-sw coverification -eve
chiportal
 

Similar to Essentials of Multithreaded System Programming in C++ (20)

Coding for multiple cores
Coding for multiple coresCoding for multiple cores
Coding for multiple cores
 
Medical Image Processing Strategies for multi-core CPUs
Medical Image Processing Strategies for multi-core CPUsMedical Image Processing Strategies for multi-core CPUs
Medical Image Processing Strategies for multi-core CPUs
 
Threaded Programming
Threaded ProgrammingThreaded Programming
Threaded Programming
 
Deuce STM - CMP'09
Deuce STM - CMP'09Deuce STM - CMP'09
Deuce STM - CMP'09
 
java_threads.ppt
java_threads.pptjava_threads.ppt
java_threads.ppt
 
Rust and Eclipse
Rust and EclipseRust and Eclipse
Rust and Eclipse
 
Rust "Hot or Not" at Sioux
Rust "Hot or Not" at SiouxRust "Hot or Not" at Sioux
Rust "Hot or Not" at Sioux
 
Here comes the Loom - Ya!vaConf.pdf
Here comes the Loom - Ya!vaConf.pdfHere comes the Loom - Ya!vaConf.pdf
Here comes the Loom - Ya!vaConf.pdf
 
Python multithreading
Python multithreadingPython multithreading
Python multithreading
 
Python multithreading
Python multithreadingPython multithreading
Python multithreading
 
Functional Patterns for C++ Multithreading (C++ Dev Meetup Iasi)
Functional Patterns for C++ Multithreading (C++ Dev Meetup Iasi)Functional Patterns for C++ Multithreading (C++ Dev Meetup Iasi)
Functional Patterns for C++ Multithreading (C++ Dev Meetup Iasi)
 
Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016
Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016
Serial Killer - Silently Pwning your Java Endpoints // OWASP BeNeLux Day 2016
 
Threads and multi threading
Threads and multi threadingThreads and multi threading
Threads and multi threading
 
Daniel Krasner - High Performance Text Processing with Rosetta
Daniel Krasner - High Performance Text Processing with Rosetta Daniel Krasner - High Performance Text Processing with Rosetta
Daniel Krasner - High Performance Text Processing with Rosetta
 
Track c-High speed transaction-based hw-sw coverification -eve
Track c-High speed transaction-based hw-sw coverification -eveTrack c-High speed transaction-based hw-sw coverification -eve
Track c-High speed transaction-based hw-sw coverification -eve
 
Cross Platform App Development with C++
Cross Platform App Development with C++Cross Platform App Development with C++
Cross Platform App Development with C++
 
Cpp17 and Beyond
Cpp17 and BeyondCpp17 and Beyond
Cpp17 and Beyond
 
P threads
P threadsP threads
P threads
 
Java Concurrency
Java ConcurrencyJava Concurrency
Java Concurrency
 
Rust: Reach Further
Rust: Reach FurtherRust: Reach Further
Rust: Reach Further
 

Recently uploaded

Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Victor Rentea
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 

Recently uploaded (20)

Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptx
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....
TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....
TEST BANK For Principles of Anatomy and Physiology, 16th Edition by Gerard J....
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
JohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptxJohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptx
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Choreo: Empowering the Future of Enterprise Software Engineering
Choreo: Empowering the Future of Enterprise Software EngineeringChoreo: Empowering the Future of Enterprise Software Engineering
Choreo: Empowering the Future of Enterprise Software Engineering
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontology
 

Essentials of Multithreaded System Programming in C++

  • 1. Essentials of MultithreadedSystem Programming in C++ Shuo Chen 2011/02 blog.csdn.net/Solstice giantchen@gmail.com @bnu_chenshuo
  • 2. Contents Challenges in multithreaded system programming Thread safety of C and C++ libraries RAII and fork() fork() and signal handling in multithreaded programs 2011/02 Shuo Chen (blog.csdn.net/Solstice) 2
  • 3. Audience: C++ programmers Familiar with Pthreads and Sockets API Knows thread safety, deadlock, race condition, etc. In a word: read through APUE2e and UNP3e (vol. 1) by W. Richard Stevens et al. All discussions are based on Linux 2.6.x, x >= 28 There are new syscalls, egsignalfd, eventfd, and timerfd x86 and x64 platforms 2011/02 Shuo Chen (blog.csdn.net/Solstice) 3
  • 4. Multi-threaded system programming Multithreading is inevitable in this multi-core era The difficulties are not learning synchronization primitives (mutexes, condition variables) ~10 functions are sufficient to do it right But understanding interactions between existing system calls and library functions Understands how threads affect system design Use it wisely and effectively Avoid common pitfalls and fallacies 2011/02 Shuo Chen (blog.csdn.net/Solstice) 4
  • 5. 11 essential Pthreads functions 11 out of 110+ pthreads functions 2 -> create and join threads 4 -> init/destroy, lock/unlock mutexes 5 -> init/destroy, wait/signal/broadcast condvars Think twice if you need more Some are okay, eg. once and key, maybe rwlock Some are bad, eg. cancel and kill, semaphores Check muduo/base for encapsulation in C++ http://code.google.com/p/muduo http://github.com/chenshuo/recipes click thread 2011/02 Shuo Chen (blog.csdn.net/Solstice) 5
  • 6. An asynchronous world Never assume the sequence of events without proper synchronization. Knows happens-before relation, memory visibility, etc. The effect of an interaction between two [thread]s must be independent of the speed at which it is carried out. --- Brinch Hansen 1973 2011/02 Shuo Chen (blog.csdn.net/Solstice) 6
  • 7. Standards and practices Although the latest official standards of C and C++ languages (C99 and C++03) do not say a word about process or thread We write multi-process and/or multi-threaded C/C++ programs in real life, as a real-world need We can’t wait it to be standardized, as standards usually fall behind practices for years btw, if there are not real life multi-threads programs , how do people what/how to standardize? We adhere to some de facto standards A lot simpler if we focus on one hardware and one OS 2011/02 Shuo Chen (blog.csdn.net/Solstice) 7
  • 8. Thread identifier on Linux Use pid_t as thread id, instead of pthread_t, on Linux pthread_tthid = pthread_self(), thid is opaque (uintptr_t) pid_ttid = ::gettid(), tid is task id, usually a small integer /proc/tid/, /proc/pid/task/tid/, ps, top all work fine How to implement gettid() efficiently? Thread local? gettid(2) is a syscall, but the output should never change getpid(2) caches the result, should gettid() do the same? What if fork(), will it caches the old value in child proc? How about pthread_atfork() to clear it up? Check muduo/base/Thread.cc for details 2011/02 Shuo Chen (blog.csdn.net/Solstice) 8
  • 9. Creation of threads A library should not create its own ‘background’ thread without prior informed consent Makes a program non-forkable Never create thread before main() Avoid creating thread in ctor of static or global object Breaks static objects constructing, eg. protobuf registering The number of threads created should be independentof system load, eg. # of connections, # of requests otherwise non-scalable Reuse threads, by assign multiple roles to it Doing IO and timer with muduoEventLoop class For simple task, do it within IO callbacks in IO threads 2011/02 Shuo Chen (blog.csdn.net/Solstice) 9
  • 10. Three ways of termination http://blog.csdn.net/program_think/archive/2009/03/14/3991107.aspx Natural death – return from thread function, good Suicide – call pthread_exit() Mudered – killed by pthread_cancel() Rule: let it die, never suicide or murder a thread Why? inherently deadlock-prone: no chance to unlock Design your program so that a thread can be waken up and safely exits For reference Java Thread.{stop, suspend and destroy} are deprecated Boost Threads doesn’t provide thread::cancel() 2011/02 Shuo Chen (blog.csdn.net/Solstice) 10
  • 11. pthread_cancel() and C++ In C, we have concept of ‘cancellation point’ In C++, pthread_cancel() throws an exception in that thread, helps unwinding objects on stack The exception must reach the outmost function, otherwise core dump: FATAL: exception not rethrown Aborted (core dumped) Always rethrow in catch(…) cause Ulrich Drepper “Cancellation and C++ Exceptions” Better: never cancel or kill a thread 2011/02 Shuo Chen (blog.csdn.net/Solstice) 11
  • 12. exit() is not thread safe in C++ exit() destructs static or global objects, (_exit() doesn’t) The destructor may try to hold a lock The caller function may have held the same lock already End up in a dead lock Check following code for an example of dead lock github.com/chenshuo/recipes/blob/master/thread/test/ExitDeadLock.cc How to quit a multi-threaded program safely? An irregular but simple solution: make a process killable, eg. p.29 blog.csdn.net/Solstice/archive/2010/10/19/5950190.aspx It’s not fault of exit(), but static or global objects Try to avoid static or global objects in C++, except for PODs 2011/02 Shuo Chen (blog.csdn.net/Solstice) 12
  • 13. Thread local __thread in g++ Thread safe by natural, unless escaped to other thread More efficient implementation, than pthread_key_t See “ELF Handling For Thread-Local Storage” In C++, must be initialized with constant-expression No __thread string t_obj("Chen Shuo"); No __thread string* t_obj = new string; Only __thread string* t_obj = NULL; More rules: http://gcc.gnu.org/onlinedocs/gcc/Thread_002dLocal.html Use pthread_key_t if you want auto destruction 2011/02 Shuo Chen (blog.csdn.net/Solstice) 13
  • 14. Use non-recursive mutex only A basic assumption of holding a mutex Once I lock it, I can modify the guarded object safely Which is not true for recursive mutex, eg. http://blog.csdn.net/Solstice/archive/2010/02/12/5307710.aspx#_Toc11928 Recursive mutexes by David Butenhof http://zaval.org/resources/library/butenhof1.html Recursive locks - a blessing or a curse?  http://www.thinkingparallel.com/2006/09/27/recursive-locks-a-blessing-or-a-curse/ 2011/02 Shuo Chen (blog.csdn.net/Solstice) 14
  • 15. Impacts of introducing threads Threading is a late patch to OS kernel Unix kernel and API formed in early 1970s First implementation of threads emerged in early 1990s Breaks lots of assumptions made during the 20 years Library functions with side effects must be revisited malloc/free, fread/fseekcan be made thread-safe with locks Functions that return or use static allocated space are not thread safe but may have thread-safe variants asctime_r, ctime_r, gmtime_r, rand_r, stderror_r, strtok_r errno is not an ‘extern int’, but a per-thread value extern int *__errno_location(void); #define errno (*__errno_location()) 2011/02 Shuo Chen (blog.csdn.net/Solstice) 15
  • 16. Thread safety of C library Individual system calls must be thread safe Be caution of interfering of same file descriptor from multiple threads Most of glibc library functions are thread safe nowadays Counterintuitively, Posix standards lists functions thatare not required to be thread safe, it's a black list. http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_09 2.9.1 Thread-Safety : All functions defined by this volume of POSIX.1-2008 shall be thread-safe, except that the following functions need not be thread-safe. Notably, getenv/putenv/setenv/system() are not safe 2011/02 Shuo Chen (blog.csdn.net/Solstice) 16
  • 17. FILE* functions are thread safe Read ‘man flockfile’, but they are not composable, eg. fseek(), followed by fread() The file position may change during the course by a different thread Wrap with flockfile(FILE*) and funlockfile(FILE*) Same applies to lseek(2) and read(2), but how to lock? Use pread(2) instead, which doesn’t change the file offset In general, a function that calls two thread-safe functions is not guaranteed to be thread-safe Just like exception-safety, thread-safety is not composable 2011/02 Shuo Chen (blog.csdn.net/Solstice) 17
  • 18. Thread safety is not composable A solution works in single-threaded program may not apply to multi-threaded program. Any solution calls two or more thread safe function are not necessarily correct in multi-threaded program What’s the time in London now? Program runs in New York string oldTz = getenv("TZ"); // save TZ putenv("TZ=Europe/London"); tzset(); // set TZ to London struct tm localTimeInLN = *localtime(time(NULL)); setenv("TZ", oldTz.c_str(), 1); tzset(); // restore old TZ This code impacts localtime() in other threads Thread safe functions are not composable unless you carefully design the interface and interactions 2011/02 Shuo Chen (blog.csdn.net/Solstice) 18
  • 19. Thread safety of C++ std library Although not required by the standard, the de facto says Unshared objects are independent: Two threads can freely use different objects without any special action on the caller's part. We call it "same level as built-in types." This applies to STL containers like map, vector, string Pure functions are safe, eg. Most of STL algorithms. The global cin/cout objects are shared by threads, and are not thread safe. Moreover, they can't be made safe cout << a << b;  cout.operator<<(a).operator<<(b); Two function calls can be interrupted by another thread Use printf(3) instead, it's thread safe and atomic. Allocators must be thread safe, as they are shared 2011/02 Shuo Chen (blog.csdn.net/Solstice) 19
  • 20. Thread-Safe vs. Thread-Efficient printf(3) and malloc(3) are thread safe, but not necessarily efficient enough, esp. on multi-cores printf(3) locks FILE* stdout, synchronizes threads not good for multi-threaded logging, we need a better lib your default malloc(3) may not optimized for multi-threads and multi-cores it may lock global heap for each allocation try tcmalloc, Google's thread-cache malloc see Intel. Is your memory management multi-core ready? http://software.intel.com/en-us/blogs/2009/08/21/is-your-memory-management-multi-core-ready/ 2011/02 Shuo Chen (blog.csdn.net/Solstice) 20
  • 21. Operate one fd in one thread Although system calls of file descriptors are safe What if a thread close a fd when other thread is block reading it? What happens if a thread add a fd to epoll watch list while other thread is epoll_wait()ing it? What happens if two threads poll same fd, and find it readable simultaneously? What if two threads read the same TCP socket but each get partial data? How do you tell which part comes first? Rule: all operations on one file descriptor should happen in one thread, make your life a lot easier 2011/02 Shuo Chen (blog.csdn.net/Solstice) 21
  • 22. File descriptors in threads File descriptors are small integers, unlike HANDLE When create a new fd, kernel picks the lowest unused one Higher possibility of cross-talk, if careless, eg. A fd shared by two threads The first thread have just close()d it The second is about to read() it But a third thread happened to create a new fd with same id (the lowest available int reused) during the period What does the second thread read from? Any other impact? Solution: manage resource with RAII idiom And use the usual technique to manage object life cycles 2011/02 Shuo Chen (blog.csdn.net/Solstice) 22
  • 23. C++ and fork() A object could construct once but destruct twice int main() { Foofoo; // call 'Foo::Foo' fork(); // fork to two process // call 'Foo::~Foo' in parent *and* child processes } It might be a problem, if Foo owns some resource that is not inherited by child process Again, avoid static or global objects in C++ In child process, the object may not be properly initialized A global muduo::Timestamp startTime(now()) is wrong 2011/02 Shuo Chen (blog.csdn.net/Solstice) 23
  • 24. RAII and fork() fork() doesn't copy all state Open file descriptors are inherited by child process But the offset of file are independent The child does not inherit its parent's memory locks (mlock(2), mlockall(2)) record locks from its parent (fcntl(2)) timers from its parent (setitimer(2), alarm(2), timer_create(2)), and others So the RAII idiom may not work well in fork()ed process A RAII class that wraps timer_create/timer_delete in ctor/dtor may fail in child process after fork() Use pthread_atfork() as the last resort 2011/02 Shuo Chen (blog.csdn.net/Solstice) 24
  • 25. C++ and threads Use scoped lock guard only, check muduo/base/Mutex.h Don't allow exceptions to propagate across module boundaries don't let exception propagate out of the thread main function, catch all exceptions in the outer-most function But, rethrow the one of pthread_cancel(), as we said before Don't allow exceptions to propagate out of your callback, esp. callbacks from C library, eg. the init_routine registered to pthread_once() Better: don't use exception in C++ 2011/02 Shuo Chen (blog.csdn.net/Solstice) 25
  • 26. Threads and fork() The fork() model doesn’t fit well in threads A fundamental flaw of PosixOSes, as other threads disappear in child, the state is not consistent in child proc After fork a multi-threaded program you may only call async-signal-safe functions in child, as if in signal handler malloc() is not safe, other thread may hold the lock when fork()ing, and no chance to unlock in the new process So does printf(), pthread_* and others. The only safe way to use fork() in a multi-threaded program is calling exec() immediately in child process And make sure set close-on-exec flag on every file descriptors in parent process for security reasons. 2011/02 Shuo Chen (blog.csdn.net/Solstice) 26
  • 27. Signals and threads The whole Posix signal mechanism is a shit Only async-signal-safe functions can be called in signal handler, also called 'reentrant functions' Most of the functions are notasync-signal-safe, except those listed in Posix standards, so it's a white list http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03_03 'man 7 signal' to get the list on Linux None of pthread_* are not async-signal-safe, you can't notify a condvar or lock a mutex in signal handler Surprisely, gettimeofday(2) is not async-signal-safe 2011/02 Shuo Chen (blog.csdn.net/Solstice) 27
  • 28. Deal with signals in MT programs Rule 1: do not use signal don't use it as IPC, eg. SIGUSR1, SIGUSR2, SIGINT, SIGHUP don't use library functions built upon signals, eg. alarm, sleep, usleep, timer_create, etc. Rule 2: when you absolutely need, convert an async signal to synchronous file descriptor readable event use signalfd in high Linux kernel version Normally, the set of signals to be received via the file descriptor should be blocked using pthread_sigmask(3), to prevent the signals being handled according to their default dispositions. or open a pipe(2), write(2) one byte in signal handler, and read(2) or poll(2) it in main thread 2011/02 Shuo Chen (blog.csdn.net/Solstice) 28
  • 29. Other resources http://pubs.opengroup.org/onlinepubs/9699919799/ http://www.linuxprogrammingblog.com/threads-and-fork-think-twice-before-using-them http://www.linuxprogrammingblog.com/all-about-linux-signals http://www.cppblog.com/lymons/archive/2008/06/01/51838.html Seven posts in http://www.cppblog.com/lymons/category/9446.html 2011/02 Shuo Chen (blog.csdn.net/Solstice) 29
  • 30. To be continued Essential of non-blocking network programming in C++ Birth of a reactor – design and implementation of Muduo 2011/02 Shuo Chen (blog.csdn.net/Solstice) 30
  • 31. Avoid static or global objects Except for PODs 2011/02 Shuo Chen (blog.csdn.net/Solstice) 31

Editor's Notes

  1. http://boost.cppll.jp/BDTJ_1_30/libs/thread/doc/rationale.html#Events
  2. http://download.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.htmlhttp://boost.cppll.jp/BDTJ_1_30/libs/thread/doc/faq.html
  3. http://udrepper.livejournal.com/21541.html
  4. http://people.redhat.com/drepper/tls.pdf
  5. random_shuffle
  6. http://www.linuxprogrammingblog.com/threads-and-fork-think-twice-before-using-them
  7. http://www.linuxprogrammingblog.com/all-about-linux-signalshttp://www.cppblog.com/lymons/archive/2008/06/01/51838.html