views:

1875

answers:

14

I was recently working on an application that sent and received messages over Ethernet and Serial. I was then tasked to add the monitoring of DIO discretes. I throught,

"No reason to interrupt the main thread which is involved in message processing, I'll just create another thread that monitors DIO."

This decision, however, proved to be poor. Sometimes the main thread would be interrupted between a Send and a Receive serial message. This interruption would disrupt the timing and alas, messages would be lost (forever).

I found another way to monitor the DIO without using another thread and Ethernet and Serial communication were restored to their correct functionality.

The whole fiasco, however, got me thinking. Are their any general guidelines about when not to use multiple-threads and/or does anyone have anymore examples of situations when using multiple-threads is not a good idea?

**EDIT:Based on your comments and after scowering the internet for information, I have composed a blog post entitled When is multi-threading not a good idea?

+2  A: 

Actually, multi threading is not scalable and is hard to debug, so it should not be used in any case if you can avoid it. There is few cases where it is mandatory : when performance on a multi CPU matters, or when you deal whith a server that have a lot of clients taking a long time to answer.

In any other cases, you can use alternatives such as queue + cron jobs or else.

e-satis
Why is multithreading not scalable? What types of things make it "hard to debug"?
Where can I get more information about "Queue" and "Cron" jobs?
CodingWithoutComments
It´s a shortcut. Supercomputers indeed prove that you can make multithreading scales at a local level, but for web apps you will always get better result using several separate small servers than a big one with threads. It´s hard to debug because of the shared ressources and synronized methods.
e-satis
Queue + cron is is used when real time is not an issue. Your code don´t perform anything but log actions in a database and a cron job pop this queue, calling the proper scripts to do te job, and using the OS multitasking capabilities instead of making you do the dirty job. Simple and handy.
e-satis
"Multithreading" is absolutely scalable. It should be obvious that you will start to reap many fewer performance benefits when the number of threads trying to execute at any one moment is greater than the number of hardware contexts in your machine, but the concept itself is infinitely scalable.
Matt J
How scalable it is depends on your OS's implementation. On Windows, for example, threads are cheap.
jeffamaphone
+1  A: 

In priciple everytime there is no overhead for the caller to wait in a queue.

Claus Thomsen
Could you elaborate a bit more on your answer?
CodingWithoutComments
Well, as i see multithread is a "bad". SO unless you have a prioritized job, like main thread in UI, or when a lot of request like on webserver where threads cannot be executed in one queue, then dont use them.If a caller(s) can wait in one queue then it is the preferred way.
Claus Thomsen
A: 

Are the processes parallel? Is performance a real concern? Are there multiple 'threads' of execution like on a web server? I don't think there is a finite answer.

Greg Ogle
I not necessarily looking for a definitive finite answer. I'm just looking for as many different opinions as possible.
CodingWithoutComments
+2  A: 

Multi-threading is not a good idea if you need to guarantee precise physical timing (like in your example). Other cons include intensive data exchange between threads. I would say multi-threading is good for really parallel tasks if you don't care much about their relative speed/priority/timing.

Michael Pliskin
Interesting. Is this something you read somewhere? Or something you discovered through your own work?
CodingWithoutComments
I didn't really work myself with physical timings, but other than that - my experience.
Michael Pliskin
+5  A: 
  1. On a single processor machine and a desktop application, you use multi threads so you don't freeze the app but for nothing else really.
  2. On a single processor server and a web based app, no need for multi threading because IIS handles most of it.
  3. On a multi processor machine and desktop app, you are suggested to use multi threads and parallel programming. Make as many threads as there are processors.
  4. On a mulit processor server and a web based app, no need again for multi threads because IIS handles it.

In total, if you use multi threads for other than un-freezing desktop apps and any other generic answer, you will make the app slower over time IF you have a single core machine.

Why? Well because of the hardware switches. It takes time for the hardware to switch between threads in total. On a multi core box, go ahead and use 1 thread for each core and you will greatly see a ramp up.

I hope that helps.

Scott
This is great thanks.
CodingWithoutComments
+2  A: 

To paraphrase an old quote: A programmer had a problem. He thought, "I know, I'll use threads." Now the programmer has two problems. (Often attributed to JWZ, but it seems to predate his use of it talking about regexes.)

A good rule of thumb is "Don't use threads, unless there's a very compelling reason to use threads." Multiple threads are asking for trouble. Try to find a good way to solve the problem without using multiple threads, and only fall back to using threads if avoiding it is as much trouble as the extra effort to use threads. Also, consider switching to multiple threads if you're running on a multi-core/multi-CPU machine, and performance testing of the single threaded version shows that you need the performance of the extra cores.

Thomee
Ah. Great quote. Never heard that one before -- ha. Also, great rule of thumb.
CodingWithoutComments
It's a mis-quote. The original is regarding 'regex'. Paraphrasing does not include changing the subject of the quote.
Kieveli
Like I said, while often attributed to JWZ, the quote itself has been around for longer, and wasn't about regular expressions prior to JWZ's usage. Given the history of the quote, I think it's still a valid paraphrase. I wasn't intending to claim JWZ was talking about the problems of threads. As I see it, the quote is about someone taking a cool tool and trying to apply it to too broad a set of problems, and creating more challenges than they solved.
Thomee
+2  A: 

A recent application I wrote that had to use multithreading (although not unbounded number of threads) was one where I had to communicate in several directions over two protocols, plus monitoring a third resource for changes. Both protocol libraries required a thread to run the respective event loop in, and when those were accounted for, it was easy to create a third loop for the resource monitoring. In addition to the event loop requirements, the messages going through the wires had strict timing requirements, and one loop couldn't be risked blocking the other, something that was further alleviated by using a multicore CPU (SPARC).

There were further discussions on whether each message processing should be considered a job that was given to a thread from a thread pool, but in the end that was an extension that wasn't worth the work.

All-in-all, threads should if possible only be considered when you can partition the work into well defined jobs (or series of jobs) such that the semantics are relatively easy to document and implement, and you can put an upper bound on the number of threads you use and that need to interact. Systems where this is best applied are almost message passing systems.

larsivi
Oh, for the application above you actually used a multi-core computer and multi-core programming to stop the threads from interrupting each other? This is where I went wrong.Your experience is insightful. Thanks for sharing.
CodingWithoutComments
+1  A: 

I would say multi-threading is generally used to:

  1. Allow data processing in the background while a GUI remains responsive
  2. Split very big data analysis onto multiple processing units so that you can get your results quicker.
  3. When you're receiving data from some hardware and need something to continuously add it to a buffer while some other element decides what to do with it (write to disk, display on a GUI etc.).

So if you're not solving one of those issues, it's unlikely that adding threads will make your life easier. In fact it'll almost certainly make it harder because as others have mentioned; debugging mutithreaded applications is considerably more work than a single threaded solution.

Security might be a reason to avoid using multiple threads (over multiple processes). See Google chrome for an example of multi-process safety features.

Jon Cage
Chrome is not a good response. They use multi-PROCESS for Security. Multi-threading affords no security at all.
Matt Cruikshank
ah. multi-processes. That IS a key difference.
CodingWithoutComments
Good point Matt - I'll ammend my post.
Jon Cage
+3  A: 

You might want to take a look at the Dan Kegel's "The C10K problem" web page about handling multiple data sources/sinks.

Basically it is best to use minimal threads, which in sockets can be done in most OS's w/ some event system (or asynchronously in Windows using IOCP).

When you run into the case where the OS and/or libraries do not offer a way to perform communication in a non-blocking manner, it is best to use a thread-pool to handle them while reporting back to the same event loop.

Example diagram of layout:

Per CPU [*] EVENTLOOP   ------ Handles nonblocking I/O using OS/library utilities
                       |                        \___  Threadpool for various blocking events
                       Threadpool for handling the I/O messages that would take long
harningt
+1  A: 

A couple more possible reasons to use threads:

  1. Your platform lacks asynchronous I/O operations, e.g. Windows ME (No completion ports or overlapped I/O, a pain when porting XP applications that use them.) Java 1.3 and earlier.
  2. A third-party library function that can hang, e.g. if a remote server is down, and the library provides no way to cancel the operation and you can't modify it.

Keeping a GUI responsive during intensive processing doesn't always require additional threads. A single callback function is usually sufficient.

If none of the above apply and I still want parallelism for some reason, I prefer to launch an independent process if possible.

finnw
+2  A: 

Multi-threading is a bad idea if:

  • Several threads access and update the same resource (set a variable, write to a file), and you don't understand thread safety.

  • Several threads interact with each other and you don't understand mutexes and similar thread-management tools.

  • Your program uses static variables (threads typically share them by default).

  • You haven't debugged concurrency issues.

Adam Liss
I think it's safe to say that if you don't know how to multi-thread, then it's not a good idea to multi-thread your application.
Kieveli
@Kieveli: A reasonable statement. Using the same logic, one might conclude that it's also not a good idea to date if you don't understand the opposite sex ... with similar consequences. :-)
Adam Liss
A: 

A common source of threading issues is the usual approaches employed to synchronize data. Having threads share state and then implement locking at all the appropriate places is a major source of complexity for both design and debugging. Getting the locking right to balance stability, performance, and scalability is always a hard problem to solve. Even the most experienced experts get it wrong frequently. Alternative techniques to deal with threading can alleviate much of this complexity. The Clojure programming language implements several interesting techniques for dealing with concurrency.

Todd Stout
+1  A: 

Multithreading is bad except in the single case where it is good. This case is

  1. The work is CPU Bound, or parts of it is CPU Bound
  2. The work is parallelisable.

If either or both of these conditions are missing, multithreading is not going to be a winning strategy.

If the work is not CPU bound, then you are waiting not on threads to finish work, but rather for some external event, such as network activity, for the process to complete its work. Using threads, there is the additional cost of context switches between threads, The cost of synchronization (mutexes, etc), and the irregularity of thread preemption. The alternative in most common use is asynchronous IO, in which a single thread listens to several io ports, and acts on whichever happens to be ready now, one at a time. If by some chance these slow channels all happen to become ready at the same time, It might seem like you will experience a slow-down, but in practice this is rarely true. The cost of handling each port individually is often comparable or better than the cost of synchronizing state on multiple threads as each channel is emptied.

Many tasks may be compute bound, but still not practical to use a multithreaded approach because the process must synchronise on the entire state. Such a program cannot benefit from multithreading because no work can be performed concurrently. Fortunately, most programs that require enormous amounts of CPU can be parallelized to some level.

TokenMacGuy
+1  A: 

Multi-threading is scalable, and will allow your UI to maintain its responsivness while doing very complicated things in the background. I don't understand where other responses are acquiring their information on multi-threading.

When you shouldn't multi-thread is a mis-leading question to your problem. Your problem is this: Why did multi-threading my application cause serial / ethernet communications to fail?

The answer to that question will depend on the implementation, which should be discussed in another question. I know for a fact that you can have both ethernet and serial communications happening in a multi-threaded application at the same time as numerous other tasks without causing any data loss.

The one reason to not use multi-threading is:

  1. There is one task, and no user interface with which the task will interfere.

The reasons to use mutli-threading are:

  1. Provides superior responsiveness to the user
  2. Performs multiple tasks at the same time to decrease overall execution time
  3. Uses more of the current multi-core CPUs, and multi-multi-cores of the future.

There are three basic methods of multi-threaded programming that make thread safety implemented with ease - you only need to use one for success:

  1. Thread Safe Data types passed between threads.
  2. Thread Safe Methods in the threaded object to modify data passed between.
  3. PostMessage capabilities to communicate between threads.
Kieveli