Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alternative to Threads

I've read that threads are very problematic. What alternatives are available? Something that handles blocking and stuff automatically?

A lot of people recommend the background worker, but I've no idea why.

Anyone care to explain "easy" alternatives? The user will be able to select the number of threads to use (depending on their speed needs and computer power).

Any ideas?

like image 904
James Jeffery Avatar asked Feb 05 '10 22:02

James Jeffery


4 Answers

To summarize the problems with threads:

  • if threads share memory, you can get race conditions
  • if you avoid races by liberally using locks, you can get deadlocks (see the dining philosophers problem)

An example of a race: suppose two threads share access to some memory where a number is stored. Thread 1 reads from the memory address and stores it in a CPU register. Thread 2 does the same. Now thread 1 increments the number and writes it back to memory. Thread 2 then does the same. End result: the number was only incremented by 1, while both threads tried to increment it. The outcome of such interactions depend on timing. Worse, your code may seem to work bug-free but once in a blue moon the timing is wrong and bad things happen.

To avoid these problems, the answer is simple: avoid sharing writable memory. Instead, use message passing to communicate between threads. An extreme example is to put the threads in separate processes and communicate via TCP/IP connections or named pipes.

Another approach is to share only read-only data structures, which is why functional programming languages can work so well with multiple threads.

like image 64
Wim Coenen Avatar answered Oct 03 '22 01:10

Wim Coenen


This is a bit higher-level answer, but it may be useful if you want to consider other alternatives to threads. Anyway, most of the answers discussed solutions based on threads (or thread pools) or maybe tasks from .NET 4.0, but there is one more alternative, which is called message-passing. This has been successfuly used in Erlang (a functional language used by Ericsson). Since functional programming is becoming more mainstream in these days (e.g. F#), I thought I could mention it. In genral:

  • Threads (or thread pools) can usually used when you have some relatively long-running computation. When it needs to share state with other threads, it gets tricky (you have to correctly use locks or other synchronization primitives).

  • Tasks (available in TPL in .NET 4.0) are very lightweight - you can split your program into thousands of tasks and then let the runtime run them (it will use optimal number of threads). If you can write your algorithm using tasks instead of threads, it sounds like a good idea - you can avoid some synchronization when you run computation using smaller steps.

  • Declarative approaches (PLINQ in .NET 4.0 is a great option) if you have some higher-level data processing operation that can be encoded using LINQ primitives, then you can use this technique. The runtime will automatically parallelize your code, because LINQ doesn't specify how exactly should it evaluate the results (you just say what results you want to get).

  • Message-passing allows you two write program as concurrently running processes that perform some (relatively simple) tasks and communicate by sending messages to each other. This is great, because you can share some state (send messages) without the usual synchronization issues (you just send a message, then do other thing or wait for messages). Here is a good introduction to message-passing in F# from Robert Pickering.

Note that the last three techniques are quite related to functional programming - in functional programming, you desing programs differently - as computations that return result (which makes it easier to use Tasks). You also often write declarative and higher-level code (which makes it easier to use Declarative approaches).

When it comes to actual implementation, F# has a wonderful message-passing library right in the core libraries. In C#, you can use Concurrency & Coordination Runtime, which feels a bit "hacky", but is probably quite powerful too (but may look too complicated).

like image 42
Tomas Petricek Avatar answered Oct 03 '22 02:10

Tomas Petricek


Won't the parallel programming options in .Net 4 be an "easy" way to use threads? I'm not sure what I'd suggest for .Net 3.5 and earlier...

This MSDN link to the Parallel Computing Developer Center has links to lots of info on Parellel Programming including links to videos, etc.

like image 26
Tad Donaghe Avatar answered Oct 03 '22 01:10

Tad Donaghe


I can recommend this project. Smart Thread Pool

Project Description Smart Thread Pool is a thread pool written in C#. It is far more advanced than the .NET built-in thread pool. Here is a list of the thread pool features:

  • The number of threads dynamically changes according to the workload on the threads in the pool.
  • Work items can return a value.
  • A work item can be cancelled.
  • The caller thread's context is used when the work item is executed (limited).
  • Usage of minimum number of Win32 event handles, so the handle count of the application won't explode.
  • The caller can wait for multiple or all the work items to complete.
  • Work item can have a PostExecute callback, which is called as soon the work item is completed.
  • The state object, that accompanies the work item, can be disposed automatically.
  • Work item exceptions are sent back to the caller.
  • Work items have priority.
  • Work items group.
  • The caller can suspend the start of a thread pool and work items group.
  • Threads have priority.
  • Can run COM objects that have single threaded apartment.
  • Support Action and Func delegates.
  • Support for WindowsCE (limited)
  • The MaxThreads and MinThreads can be changed at run time.
  • Cancel behavior is imporved.
like image 33
Fahad Avatar answered Oct 03 '22 01:10

Fahad