Good Books On Programming With Threads?
uneek writes "I have been programming for several years now in a variety of languages, most recently C#, Java, and Python. I have never had to use threads for a solution in the past. Recently I have been incorporating them more in my solutions for
clients. I understand the theory behind them. However I am looking for a good book on
programming threads from an applied point of view. I am looking for one or more texts that provide thorough coverage and provide meaningful exercises. Anyone have any ideas?"
Probably not what you're looking for, but Real World Haskell is soon to be released and has chapters on concurrent and multicore programming and software transactional memory. Even if you're not interested in Haskell per se, STM is kind of an interesting idea.
Pthreads, Java threads and .NET threads are implemented differently. If you need a good Java book, just pick up one of the "Core Java" books that covers threading in one of its chapters since Java threads aren't that complicated. That said, with Java applications (the platform I know pretty well), if you're doing "enterprise" development it's best to avoid using them and let the application server do its black magic for you.
I'm still getting the hang of Threading in C# myself, but I found this eBook immensely helpful in getting me understand some of the difficult issues such as Thread Safety, Cross-threading issues, Race Conditions, and Event-Delegate pairs.
http://www.albahari.com/threading/
Concurrent Programming in Java is more or less *the* book on good practices for multi-threaded programming for Java, with many lessons that apply to other languages as well.
The Addison-Wesley book mentioned by the parent is "Programming with POSIX Threads" by David R. Butenhof. It's what I used when I needed to get up to speed on p-threads in a hurry - clear and easy to follow. P-threads are what's in Darwin, (and so BSD) Linux, and I'm guessing based on POSIX compliance, just about every commercial flavor of UNIX. (Presmuably, OpenServer uses fraying threads)
Most important rule of thumb of multi-threaded programming is to avoid it if possible. Maybe hardware (multi-core) will change that, maybe you feel the scheduler can't do its job as well as you can and maybe you feel it's more intuitive. But, often is the case, that you're just adding more complexity to your code resulting in more difficult bugs and harder maintenance for others. Keep it simple.
Man, I have to disagree with you. That kind of dinosaur thinking will hold back progress. Multi-core is the future and multi-threaded apps are exactly what's needed to fully utilize its potential. I'm sorry if its too hard for you to debug but its just the way the cookie crumbles.
for the morbidly curious, there's even a pthreads library for windows. LGPLed
http://sourceware.org/pthreads-win32/
Self proclaimed typo king, and inventor of the bear destroying coffee table (patent not pending).
The thread model has some fundamental problems, but since they seem here to stay there are some things you should keep in mind, nicely summarized in this article(pdf).
Article also available in html if you click on the first computer.org link from google. Hmm, why does it work from google and not from slashot?
Here's one I found useful: Multithreading Applications in Win32 by Jim Beveridge and Robert Wiener. It's a little dated (no coverage of .NET, for example - it's more focused on C/C++), but it still provides a good introduction to threading and synchronization on Windows.
If you can find an inexpensive used copy, it's worth a read.
Some background in parallelism is helpful for mastering threads.
I learned from this book:
http://www.lindaspaces.com/book/
C-linda never caught on, but it's not hard to read the examples and apply them to pthreads, java, MPI or whatever framework you're using.
Herb Sutter has been doing a lot of work on this stuff over the last 10 years and his blog is full of stuff on what you should do... it's not too nitty gritty in terms of languages and stuff, but it's very informative in terms of understanding the issues and what not. Check out http://herbsutter.wordpress.com/.
Some rules of thumb that I've found useful:
I believe that following strict OO guidelines is even more important when dealing with concurrency than when dealing with general ideas in software... and let's face it, it's extremely important even when not dealing with concurrency :)
This sig used to be really funny...
Howsabout books or sites on Python threaded programming? I'm going to be working on a project in a short while which will require the use of GTK and twisted together in a sort of network scanner system with asynchronous results.
As much as I love Python, it does have some weak points, and threading is one of them. From the python documentation:
The Python interpreter is not fully thread safe. In order to support multi-threaded Python programs, there's a global lock that must be held by the current thread before it can safely access Python objects.
Threading is there, and I'm sure some decent documentation exists somewhere. But the GIL (global interpreter lock) generally means that there are better ways to approach the problem in python, i.e. processes instead of threads.
It's a point of contention in the community, and the GVR-BDFL point of view is that any attempt to remove it makes Python a lot slower, so he won't.
While I don't use twisted, I am given to understand that it does most of its asynchronous stuff using callbacks - you may be able to leave most of the concurrency to it and avoid the process all together...
-V-
Who can decide a priori? Nobody.
-Sartre
Multi-core is the future and multi-threaded apps are exactly what's needed to fully utilize its potential.
For each application you name that is benefited by threading, someone else will be able to name one that isn't. Some processes simply are not parallelizable in a meaningful way, where meaningful is defined as in speed of execution not as in the interactive extravaganza of "looky how I can clicky the button while it's still doing hard maths".
There's a good bit of reading about the subject, although much of it is boring and is often difficult to apply to real-world situations. Amdahl's law in many situations can predict if it's worth bothering with multithreading (or other forms of parallelizing) quite easily.
A tool like cat or grep has no benefit of being threaded since it's a simple sequential task. Suppose you were to multithread "cat" into one thread that reads from disk, and another that displays a line of text on the screen. Thread 1 will spend most of its time waiting for I/O, and thread 2 will spend most of its time waiting for thread 1 to pass data. Except now, your multithreaded cat has a somewhat complicated synchronization mechanism on top of it that makes it a bit harder to debug and probably eats some extra cycles as well.
While the previous example is overly simple, there are plenty of tasks that are a lot more complicated but simply have no benefit of being threaded, because they spend more time waiting for I/O than actually calculating or because the algorithm is simply not worth parallelizing because there is no benefit in speed.
Another example would be an application divided in 3 steps. Step A and B can be executed at the same time independently of each other, while step C depends on step A and B. Both step A and B can be written to use two threads, and if they'd use two threads they'd run in half the time of their non-threaded equivalent. On a dual core machine (or 2 CPU machine) running step A multi-threaded and then step B multi-threaded takes 1 hour. In the other case, running step A and at the same time (on the other core/CPU) running step B single threaded also takes 1 hour. At this point you gain nothing by threading. Of course here I assume that I/O by both processes at the same time doesn't create some sort of delay. But if you're working with large enough data sets (more than you can keep in memory) this becomes less and less of an issue since the I/O overhead will already be there anyway.
If you add to that the fact that threading (especially synchronization) is a subject that is not well understood by everyone (in the "find me out of 200 programmers fresh from school, 10 who can write a program that benefits from multi-threading and actually works" sense), threading suddenly becomes less appealing if there aren't any clear benefits for the application you're working on.
The reason I mention that last part is that because so many schools give kids the "make two threads count to 100 then exit" exercise but fail completely at getting the message across of the fact that most of the time the threads actually need to synchronize with each other. They'll give this long lecture about the dining philosophers problem without actually SHOWING them what that means.
In conclusion: it depends on a lot of factors (size of your dataset, how well your algorithm can be split up in parallel tasks, ...) if your process benefits from threading or not, and you should evaluate at design time using Amdahl's law if there's an advantage or not. If your results in a multithreaded environment are only marginally better, the economical factor of cost of development time suddenly weighs in very heavily.
Having said that: if you're a programmer, have fun with threads at least once. Write something silly in your spare time, it can be an amazing amount of fun and often offers an interesting way of approaching future problems.
Erm, the tenets of programming usually involve the general concept of "Eliminate the unnecessary." Therefore, the parent is correct: if multi-threaded processing is unnecessary, avoid it.
Although unnecessary, threading usually simplifies a program rather than adding complexity. The only caveat is that you understand threading. In my experience I've used threading to greatly reduce the size and complexity of solutions that either were or could have been implemented without them.
Who is John Galt?
Programming Erlang
you had me at #!
There is a new multiprocessing module 2.6 (and eventually 3.) that does allow for true multiprocessing. It uses an interface similar to but not exactly like threads, but actually is forking off new processes and using pipes to communicate in the background. It is possible to use shared memory between processes to give you all the benefits (and pitfalls) of threads.
On systems where spawning processes is cheap (like Linux) I think it could be pretty useful. While certainly not as low-overhead as pthreads, it should finally allow Python to utilize multicore CPUs if you code your program the right way.
Most important rule of thumb of multi-threaded programming is to avoid it if possible. Maybe hardware (multi-core) will change that, maybe you feel the scheduler can't do its job as well as you can and maybe you feel it's more intuitive. But, often is the case, that you're just adding more complexity to your code resulting in more difficult bugs and harder maintenance for others. Keep it simple.
I'm going to have to disagree with you on this one. Especially in Java client side rich GUI apps, background threads are one of the most useful components to ensure a responsive interface when dealing with asynchronous requests. They really only need two and a half pieces to implement them easily and efficiently. The first component is the request itself, either a subclass of java.lang.Runnable or javax.swing.SwingWorker. The second is a callback handler. The half piece is the shared data structure, and it's only a half piece because you'll want to use the synchronized collections wrapper to get a (you guessed it) synchronized collection.
Brushing up on those pieces will give you the background you need to not block the UI whenever something needs to happen. Threads aren't hard, they just take a little thought.
Look, moderators, that's offtopic. Not flamebait, offtopic.
Flamebait: being an asshole/provoking others into being an asshole. eg "Linux threads suck ass."
Troll: posting shit in order to get a response by people who think you're serious. eg - "I've been a lunix users for years. I wish it had thread support. That's why I'm switching to vista. "
Offtopic: anything unrelated to threading.
Those who just say "don't use threads" are just saying "I don't know how to use threads or I haven't been careful when using them, so stay away from them." The same could be said about certain computer languages.
Specifically, you need to be VERY careful of what you do with threads:
* ALWAYS Lock shared resources.
* Be careful of what order you put the locks into, otherwise you can stumble upon deadlocks.
* NEVER, EVER, update the GUI from a secondary thread unless you really know what you're doing (hint: You don't know). Gui programming doesn't mix up well with multithread programming.
* Dealing with detached threads is a headache. Use joinable threads instead.
* If you're developing a high-performance, low-latency app (i.e. multimedia), you may need to research on lock-free and wait-free programming (not for the faint hearted, tho). But if you're just starting with thread programming, I don't recommend it.
* Also, start making simple threaded programs as exercises. Change the order of the locks to see how you can screw up.
For research, before purchasing a book, search Wikipedia for the following fundamental topics:
- mutex
- critical section
- condition variable
- semaphore (these are the four fundamental synchronization primitives)
- read/write lock
- memory barrier
- RAII (How to make your threads exception-safe)
- dining philosophers problem
- Priority inversion (a typical problem with multithreading)
- Deadlocks
- Concurrent programming
Also Google for:
- joinable threads
- detached threads
- thread execution barrier
Good luck!
I don't necessarily mean the language, but the principles therein, they can be used in any language. The main point is that it avoids low-level locking (mutexes) and ensuing contention by never sharing memory between threads ("processes" in the Erlang VM) which would require it. Instead, data is passed as messages between threads, which work like event handlers then. In languages like C, you can also model this non-shared data by simply using read-only shared data, when you make sure that data isn't modified, you don't need to copy it between the threads.
Other than that, in event-based environments (typically window-based programs) you can often replace threads with a timer, which fires an event with the desired frequency. If all you need is to do something repeatedly and sleep in between, that works pretty well and and completely without locking. If you need a worker thread to do intensive computations in the background, that is not the way though.
cheers
Uli
(Ulrich Eckhardt)
I took some classes taught by Allen Holub. Very smart guy, and I certainly enjoyed his book.
He provides good solid explanation on functional models for queue design and listener patterns. He also discusses some pitfalls of threads in Java.
http://www.holub.com/training/java.threads.html
http://www.amazon.com/Taming-Java-Threads-Allen-Holub/dp/1893115100
# for x in `find '.' -name "*.c" -print`; # do perl -pie "s/==/=/ig" $x; done
That might seem wrong given that Python lists threading modules, but just look at Python's GIL to know what I mean. As in, no matter what you do, Python will still be running on one core. So, if you just want a performance boost because of a lot of I/O, then threads can get you there. Unfortunately, if you want to take advantage of a multi-core CPU with Python, Python's threads won't get you there. There has actually been a lot of discussion on this topic, but Guido just refuses to do it. The interpreter has no threads and the lib is not thread safe.
If you want to do multi-processing with Python, look at its subprocess module.
Guido's blog post on the GIL:
http://www.artima.com/weblogs/viewpost.jsp?thread=214235
The FAQ entry on a (fallacious) reason why they won't remove it:
http://www.python.org/doc/faq/library/#can-t-we-get-rid-of-the-global-interpreter-lock