Ask HN : Have you ever programmed with threads?

9 points by dan_sim ↗ HN
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).

37 comments

[ 2.6 ms ] story [ 92.8 ms ] thread
I've worked on projects that use threads before, but this week I started actually writing threaded code myself for the first time on a pet project (real time ray tracer).

I 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.

Try to make the handoffs between threads as coarse-grained as possible. Passing data between threads means your thread acquires some lock, leaves the data there, then the other thread has to acquire the lock before getting the data -- both situations could involve a thread blocking and going to "blocked", then "runnable", then finally at some point in the future actually being executed and doing their work. If the tasks you're parcelling out are too fine grained and require too much communication, the scheduling overhead will outweigh the parallelism -- and you could be getting effectively singlethreaded performance plus overhead.
There is nothing worse than being the person who gets called in to fix the failing threaded code that was written by someone who sort of knows threading but not really.

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.

With mutli-core CPU now almost ubiquitous Threading is completely essential (outside of a GUI). I can't imagine developing a scalable application without threads.

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.

For a startup, Visual C++ in 1997-8. Challenging, certainly, especially when supposedly thread-safe libraries turn out not to be, but quite rewarding.
Yes, on personal and enterprise. Mostly just used for releasing the UI while the app is doing the dirty work...but on several occasions got lots of speed boosts by pooling db connections and shredding complex files on different threads, also doing image generation for video by hijacking 100% of my CPU to build frames as quickly as possible. Not for the impatient -- No room for progress bars :)
I've done quite a bit of work in Java in threads. They're not as bad as people say if you know what you're doing. However, like memory management, they're really easy to mistakenly believe you actually know what you're doing.

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 developed a Windows service in C# that would listen for TCP connections, spin off a new thread and perform a text to speech translation as required.

I'm not university educated, so the biggest hurdle for me was becoming familiar with mutexes and semaphores.

Concurrency is easy for most projects if you stick to simple design patterns. It is hard for very high-performance programs.
A lot of time. Work parallelization, network servers, P2P, UI background workers, long running reports, etc. Mostly in C++ and Java.

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.

Yes. Enterprise glueware. Python 2.6 Queue() objects just worked for my dataset.
All the time -- in Java, if you use java.util.concurrent, you don't have to deal with much of the complexity -- a LinkedBlockingQueue and producer-consumer pattern will solve 80% of real-world business threading problems just fine.

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.

"or just put synchronized everywhere"

Won't you deadlock this way?

Depends on what you're doing. Synchronized locks on the instance (or class if you're using a static method) and the locks are reentrant -- a thread holding a lock can reacquire it as many times as it wants.

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 :)

That statement was oversimplified. Its funny I've actually hit head on people who didnt understand "critical sections" and such and just added synchronized everywhere and even that didnt help because they were locking an independent object vs a shared object that had to be locked in order to create a critical section.

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.

Multi threaded servers on video dispatch devices. Simulations of processors. Convertions to processes from threads for a video display utility. Embedded display utility. Robotic control devices.

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.

All the time. Almost every asynchronous call in .NET uses the process threadpool. Also, anything with a UI typically needs to use a least a few worker threads to remain response while doing real work.
Mostly personal projects. A web crawler (multiple crawl threads) and a graphical display (network thread, rendering thread, periodic data processing thread).
'99-'01, a streaming video app-layer multicast startup, the client SDK (serverside we were pure evented) --- thread-per-session, worker thread to drive an event loop. Most memorable: debugging thread serialization in Quantify; even after you got to correctness, you still had weeks of effort to make sure things were actually parallelized.

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.

Enterprise bank transaction processing software, late 90s. Communications software as part of the same system. Visual C++

The multithreading was much easier than I had expected based on the way people talk about it.

For those doing Java coding, this is _the_ book to have http://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/...

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).

Java, for a class I took in my senior year. We were asked to write a Diffie-Hellman key exchanging chat application. I used threads to do non-blocking user input. After turning it in, the professor remarked that it didn't need to run continuously, but that my work was good. :)
I've used everything from pthreads to goroutines to Those Things That Ruby 1.8 Calls Threads Even Though They're Not Really. It's not that multithreaded code is inherently hard, it's just that it increases the number of interactions you have to think about exponentially. If you're used to thinking of programs as a procedural set of state manipulations, you will be incapable of reasoning about a multiprocessing system because between every two steps in your algorithm there can be an arbitrary number of steps from other algorithms which will wreak havoc with your state.
At least 3 different classes had me using threads at some point(c, pthreads library). I had to write 2 different web servers. Both were multi-threaded. One had to serve static files from a directory, the other needed to implement a simple web service outlined by the teacher. For a separate grade, we had to make the web service one implement a threadpool.

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.

Yes, but we've actually had to switch from threads to a fork() model for reliability reasons, in our main usage scenario.

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).

Any chance you're using WinCE and are loading graphical resources? There's a bug somewhere that makes that incorrectly OOM. There are workarounds though.
Yes, most recently with GUIs where the the graphical bits can't just sit there. Work-related but hardly enterprise.
Does event-based programming in javascript count? If so, then yes.

Also, it's ridiculously easy then. Setting up mutexes are a cinch with closures.

Er.... like almost all the time. Getting used to them means that you read code in a slightly different way as well, so I highly recommend it. That said, I do try to avoid them as long as it doesn't degrade user experience. However if you're going to build an app of any great consequence you're probably going to need them. A big help (if you're new to them) is viewing the threads as players in a turn based board game where your lines of code are squares on the board and everyone gets a random roll.

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.