Ask HN : Have you ever programmed with threads?
Everyone knows about how threads are hard to program with but I don't know a lot of people who really used them.
If yes, tell us on which occasion (personal project, enterprise app, startup).
If yes, tell us on which occasion (personal project, enterprise app, startup).
37 comments
[ 2.6 ms ] story [ 92.8 ms ] threadI understand much of the theory but without practice it's hard to know what to do, and so far my profiling has shown that my attempts at threading are slowing down the program, so I've still got a lot to learn.
I've been saying it for years, most people can not hold all the information they need together to write a complicated threaded system. It is hard and most people do not keep the level of concentration and focus required to use threads beyond trivial to simple use cases.
There is a language called Fantom which purports to be "thread safe" I believe by serializing objects between threads, so the data in the objects could easily become stale if not designed correctly.
Or C libs e.g Plan9, libtask
The downloadable version of BCC uses threads in at least three ways: the embedded HTTP client runs in its own thread (to avoid blocking the GUI), the printing logic runs in its own thread (ditto), and about a dozen threads do a bit of a dance to verify the Registration Key. (Took me about an hour to code up -- probably wasted time.)
The online version of BCC just handles everything by process separation and message passing. I prefer this model to threads, as it imposes rigid discipline about data sharing/sychronization/etc, and it makes it easier for my brain to grok the consequences of changes which look trivial.
I'm not university educated, so the biggest hurdle for me was becoming familiar with mutexes and semaphores.
It's really not too bad. One thing to remember is to stick with simple design. Another thing is to stick with lower level API, the one the OS or language provides. Avoid high level library. If you can't avoid, insist to have the source code. There might be bugs are in the library. Also the high level library tends to have sparse documentation to document their behavior in detail. In multi-thread programming, you need to know every detail and every assumption about the API.
If you need to go beyond that, you've gotta make sure you understand the java memory model and the way monitors work -- or just put synchronized everywhere -- but that's still pretty straightforward once you get it all straight.
Won't you deadlock this way?
But yeah my comment was a little imprecise :) If you're using a bunch of different objects which have interactions, using synchronized "everywhere" could very well lead to a deadlock :)
So yea read up on multithreading, its extremely important to know, but hey my friend worked 4 yrs in .net and just started learning multithreading. So its not always needed.
They're a hammer. I suggest people also learn the screwdriver (process based development) well enough they can make a choice between nails and screwdrivers.
Next gig, did multi-process with shared memory (think "opt-in" concurrency instead of "opt-out") and modelled synchronization on distributed systems concepts (commit protocols) instead of locks. Worked peachy.
The multithreading was much easier than I had expected based on the way people talk about it.
You never know when that library designed without threads in mind will end up in a threaded environment (which one could argue is part of the problem with leaving concurrency up to the coder in the way that Java does, versus building it into the language the way Erlang does).
I've also played with Ruby 'threads'(not really threads). For a databases class, I made a simple youtube-like clone that let users upload, tag, and comment on videos. When a video was uploaded, I needed to convert it to a flash-compatible format. I spawned a separate thread to handle this. If there were a bunch of people all uploading around the same time, you would end up with lots of extra threads hanging around converting video. I realized that this idea would never scale when I made it, but the timeframe given for the project didn't really allow me to implement a more scalable solution. I used a library off github called Spawn.
On the subject, I recently saw a great talk by Joe Damato and Aman Gupta at the Ruby Hoedown in Nashville covering different threading models. Some of their code has made it into Ruby Enterprise Edition.
Our C# software has to integrate with buggy third party C++ plugins which amongst other things may crash or completely fragment the address space (hello OutOfMemoryException when there is 1GB free).
Also, it's ridiculously easy then. Setting up mutexes are a cinch with closures.
Some uses (personal (of various sizes) and enterprise):
- Background worker that wanders off, does some shit and then says: "yo, I finished".
- Subsystems and services: Sometimes you just have "stuff" that is going on. An example would be a little doohickey I got monitoring the USB. It handles a little protocol so it can identify stuff our system knows about that gets plugged in (on any port). This is so when the "main" part of the app asks for an "external XYZ" device it can return the device (or a "null" Object if it is not connected).
- To preserve your intentions: If you broadcast events with your own thread it is possible for a consumer to chomp on your thread's processing time, so sometimes you need to spin off a background thread/s to do the event firing to free you up so you get back to your job.