Multi-threaded Programming Makes You Crazy? 166
gduranceau writes "Help! My program deadlocks! I got several concurrent threads that write the same variable! Everything goes well on my mono processor but becomes an incredible mess on that 16 CPU monster! And of course, as soon as I add traces, problems disappear... Don't panic! Calm down and take a deep breath. "
Use the right tool (Score:4, Interesting)
Oh wait. I was supposed to praise the NPTL tool, wasn't I. Um... well... it's very nice. And they've got... um... penguins on the homepage. Oh, and look! It's GPLed! Wow. Just... um... wow. Hey, did you know that the author of Minix wrote a book [amazon.com] on OS Design? Really. It even covers the basics of multi-threading. It's pretty cool, you should... um... check it out. Yeah, that's the ticket!
Re:Use the right tool (Score:2, Insightful)
And the best part is you avoid that feeling... ya know.. much like that time you saw the Donkey Show in Mexico on Spring Break... that really strange feeling you get when you use Java... and no matter how much you shower... it just won't wash off...
Re:Use the right tool (Score:2)
I think that was because of a lack of good, cheap and or free tools. Back in the early 80s you could buy Turbo Pascal, Turbo C, and Turbo Basic for under a hundred dollars each. Then came Microsoft's Quick Basic
Re:Use the right tool. Forget ADA! (Score:2)
Re:Use the right tool. Forget ADA! (Score:2)
Shame really. Transputers were a great bit of kit, just underfunded, over-expensive and too far ahead of their tim
Re:Use the right tool (Score:2)
Yes there is now a few free and or cheap Ada development tools. But there are many more C, C++, Java, Perl, Python, Ruby, and PHP bindings, libraries, development environments and a much larger code base to work from.
Ada is much like Scheme, Haskell, and SmallTalk. Very good tools, not often used. I wonder what would have happened if Borland had made a TurboAda. Would it have become super popular or would it have done as well as Turbo
Re:Use the right tool (Score:2)
I think they would have, if the DOD hadn't mandated that there be NO subsets of Ada. That meant that every implementation had to support multithreading (among other things), which would have been difficult on DOS since it didn't even have a scheduler, let alone threads.
Re:Use the right tool (Score:2)
Re:Use the right tool (Score:2)
Ada is tightly knit with C. You can import C functions with primitive data-types directly into Ada. You could write a script that will convert a C header file into an Ada header file (ads) containing all the wrapper code necessary to import all of the C functions.
OpenGL, for instance, espe
Re:Ada (Score:2)
Ada was considered a BIG language when it came out. Big as in complexity. The C++ folks used to make fun of it. That's before they added templates to C++, which makes Ada look simple by comparison. Ada also came with a large set of libraries. But nowhere near what Java now comes with standard.
Anyway, when I first started learning Java, I thought that it was almost more similar to Ada in spirit than C or C++. The set of libraries seemed similar, as well as the m
Re:Ada (Score:2)
How about a runtime you can use on a cell phone?
Re:Ada (Score:2)
The real problem comes in when there's some cutsom hardware with a co-DSP or something like that.. since these compilers are generally customized heavily for a specific language (ie, C).
Java no panacea -- must know what you're doing (Score:5, Informative)
First off, that in itself will not prevent deadlock. Secondly, it's damned inefficient.
Look: there's just no way around it. If you want to do effective (i.e. low bug, high performance) multithreaded programming, you simply have to understand what you're doing. Ultimately, the tools of your trade will be mutexes, condition variables, semaphores, etc -- the O/S primitives. Don't rely on your programming language to "automatically" use these for you, blasting out mutexes machinegun-style. Instead, figure out the logic of your program. You probably need only a small number of mutexes.
A key to effective multithreaded programming is to adhere rigidly to certain programming practices. It must _NEVER_ be the case that 2 threads have write access to a given item at the same time. Duh. But you can use fancy programming tricks to, in effect, automatically add run-time assertions to your code which assure that this practice is being adhered to. In production mode, you remove these runtime assertions.
Another good practice is, if you really need to have multiple mutexes, to arrange them into a hierarchy. When a top-level mutex is locked, no other mutex can be locked. When a second-level mutex is locked, only top-level mutexes can be locked. Etc. This hierarchy can be verified at runtime, in debug mode. Adhering to this regime will go a long way to removing the possibility for deadlocks.
Bottom line: you really have to know what you're doing in order to write good multi-threaded code. You should take the time to really study that problem space. An excellent book I've found for this purpose is "Concurrent Programming in ML". (I know -- nobody uses ML. So what? Learn the language just for the purpose of understanding the book. Then, you can apply your knowledge to any domain you're working in).
Re:Java no panacea -- must know what you're doing (Score:5, Informative)
Batman was right that after using Java's threading this NTPL trace looks pretty lame. Not only is the threading and locking in Java braindead simple, but the JVM actually tells you what is wrong. For instance it detects deadlocks and gives you the complete call trace of each deadlocked thread.
Other languages have good locking too (ruby for instance), so it's more that everything is difficult and crappy in C and its kind. I guess if you are stuck writing a threaded application in C in the first place this tracing library could be useful. Of course if you use the heap you're going to also want to replace malloc/free with a fast multithreaded version and then do a bunch of hacks so that it isn't ridiculously slow (locking on every free()... now *that's* inefficient).
Re:Java no panacea -- must know what you're doing (Score:2)
And no, it is actually perfectly fine for 2 or more threads to have read or write access to the same variable as long as it's atomic read/write... you just have to know what that means for your program.
This isn't necessarily true on multiprocessor machines. One of the extra things that mutexes do under the covers is execute memory barriers as needed to ensure the semantics are always what the programmer would expect. Without those barriers, even updates that are guaranteed to be atomic may be seen out
Re:Java no panacea -- must know what you're doing (Score:3, Informative)
Yes what you say it true, but these are all implications of atomic read/write... It follows logically from having caches
Umm, no, it has nothing to do with atomicity, nor is it because of caching.
Atomicity just guarantees that the atomic change is seen fully or not at all. It makes no guarantees about what other changes will be seen. And the problem doesn't have anything to do with caching, assuming the caches work properly (and they do). The caches maintain coherency as needed between each other and
Re:Java no panacea -- must know what you're doing (Score:3, Interesting)
None of these things are given; there's no such thing as "the concept." The designer of the language decides what guarantees to give the programmer and what latitude to give to the compiler, as well as what structures are provided to mana
Re:Java no panacea -- must know what you're doing (Score:2)
Essentially, the language designer decides what concepts the users of the language must understand and employ. C and C++ expose the programmer to the full complexity of machine
In this case, so does Java. Java also gives you no guarantees that reordering won't occur unless you use some synchronization primitives. Java 1.5 provides a richer set of primitives, including a definition of "volatile" that is safe from reordering, but the programmer still has to understand the issues.
None of these things ar
Re:Java no panacea -- must know what you're doing (Score:2)
If the CPU or MMU reording causes problems, you're probably doing something wrong/stupid in the first place.
Not at all. There are all kinds of common, proper usage scenarios where reordering will screw you without a memory barrier. A more realistic example than the one I already gave is a linked list. When inserting an entry into a linked list, if you're careful about the order in which you make the pointer assignments -- and if you know that pointer assignments are atomic -- you can theoretically all
Re:Java no panacea -- must know what you're doing (Score:2)
So, if you're doing multithreaded programming with Java, you're "encouraged" to have helter-skelter mutexes (i.e. a mutex on each "structure", aka whatever-you-like-to-call-it). That's dangerous and inefficient. On a surface level, it seems kinds of nice. Because of that feature, you can say "Java is multithreading
Re:Java no panacea -- must know what you're doing (Score:2)
I have certainly never felt that java has "encouraged" me in any way to make lots of mutexes.
Re:Java no panacea -- must know what you're doing (Score:2)
Re:Java no panacea -- must know what you're doing (Score:2)
The only claims I've seen by others is that it is easy to do multithreaded coding in Java, because the language was designed with it in mind. For example, consider this:
"myMutex" can be any object. "synchronized" is syntax. Only the thread that "won" the myMutex object will be running the code inside the braces; any other thread t
Re:Java no panacea -- must know what you're doing (Score:2)
Refer to the post to which I originally responded:
What does that mean -- "designed for multi-threaded programming" -- except that the language itself has native capabilities to support multithreading? Java does have such capability, but my argument is that the native capability is in
Re:Java no panacea -- must know what you're doing (Score:2)
I would +1 the rest of your comment but must take exception here. The Java language standard makes useful sequencing and atomicity guarantees that make it clear exactly when a mutex is needed. C++ does not. A dumbed-down version (bec
Re:Java no panacea -- must know what you're doing (Score:2)
It is still true. Java guarantees the size of things like int no matter what the platform, and guarantees atomicity of accessing such variables. Of course, on 64-bit platforms you naturally
Re:Java no panacea -- must know what you're doing (Score:5, Informative)
It must _NEVER_ be the case that 2 threads have write access to a given item at the same time.
Two clarifications:
First, it's okay to allow multiple threads write access as long as the writes are guaranteed to be atomic and as long as the order of atomic writes doesn't matter. In practice, that second restriction usually means you need locking.
Second, it's often important that one thread not be writing an object while one or more threads are reading it. In other words, multiple writers aren't the only problem.
Re:Java no panacea -- must know what you're doing (Score:2)
I like to start with a very conservative locking system and then go thru it a few hundred times to improve performance.
Exactly. "Correctness first, speed after" is always good advice, but it's really important in concurrent programming, just because it's so easy to get wrong.
Where possible, when tuning for performance I like to leave the more conservative locking structure in place, so I can turn it back on with a compiler (or even run-time) switch. Then whenever I start adding features or fixing bug
Parent post is simply WRONG (Score:2)
"Concurrent Programming with J2SE 5.0"
http://java.sun.com/developer/technicalArticles/J2 SE/concurrency/index.html [sun.com]
and
"Concurrency Utilities Overview"
http://java.sun.com/j2se/1.5.0/docs/guide/concurre ncy/overview.html [sun.com]
There's much more to concurrency in Java (especially Java 5) than simple target-object synchronization. (For example, you can set up queues to pass safely from one thread to another.)
You might also wa
Re:Use the right tool (Score:3, Insightful)
Java has a noticeable initial coding and running overhead, but while the application starts to grow, it fades away. The only *free* and open alternative in these terms is python, which somewhat provides the
Re:Use the right tool (Score:2)
Not always. If the level of parallelism is very fine, then the synchronization costs would overwhelm any gains from running in parallel. I really don't understand your overall point, either. Running a scalable multithreaded app over as many CPUs as possible is exactly what you wa
Re:Use the right tool (Score:2)
i give you a simple example, your application is using a third party library that you have not optimized for threading. the api contains a block like this
while (condition) {
x++;
}
now imagine that you have shared the x between your threads and that it gets incremented 1000 times. this means 15 000 low level threading messages sent between the cpus that "yo you cpu, this equals now to this". the x may be buried into some deep hierarchy of structs
Re:Use the right tool (Score:2)
I wouldn't recommend Python for work on multi-cpu systems. It has a global lock that means that only one thread may be executing python code at a time. Python only scales in a cluster-like fashion, not with big & fast systems.
From the `popular` languages, php seems to be only one who is totally ignoring threading
Re:Use the right tool (Score:5, Informative)
The correct tool is called a brain, but first the brain must be configured properly.
Deadlocks are one symptom of poor program logic, and are designed into the program due to lack of proper controls. They frequently occur when a program is not designed before it is written.
See "dining philosophers [google.com]" for an explanation of this, and several methods to prevent this situation.
Tracing tools are all well and good, but if one starts out with correct logic in the first place then one won't spend more time debugging than programming.
Always remember that a digital computer is a logical computing device. If you give it a series of instructions which do not ALWAYS have a logical solution, then it will choke
-Adam
Re:Use the right tool (Score:3, Informative)
There are some good tools for the job. Relatively speaking, Java isn't one of them.
While Java does include some built-in support for multithreading primitives, its underlying model (using locks on data to prevent simultaneous access) is the same as many other mainstream languages today. Thus it suffers from the same weaknesses, including deadlocking, and potentially also things like potential priority inversion, depending on how clever the implementation of the concurrency tools is.
If you want serious m
Re:Use the right tool (Score:3, Insightful)
In other words, Java provides built-in support for traditional concurrency methods, rather than making you reinvent that particular wheel. Which means that if you've done multi-threaded programming before, Java probably supports whatever techniques you've (presumably successfully) used. I fail to see how
Re:Use the right tool (Score:2)
What I don't like about Java's concurrency is a) it forces ALL objects to have a mutex/condition variable structure (stupid wasteful overhead), and b) the condition variable support doesn't allow you to do things like share a mutex for separate condition variables. Yes, it makes it easier to not screw up (by using the wrong mutex entirely), but it also takes away a lot of flexibility.
For example, it is more difficult and less efficient to implement reader/writer interlock models without the ability to hav
Re:Use the right tool (Score:2)
You're right! It would be better to get a technology designed for multi-threaded programming. But then you go on to push Java? I'm confused.
Now, granted, Java does provide builtin support for concurrency. Although that support is an implementation of the 30-year old monitor [wikipedia.org] concurrency primitive, which even one of its principal inventors (Tony Hoare) long ago abandoned in favor of better things [usingcsp.com]. Not to mention that Java's implementation of monitors is known to be broken [brinch-hansen.net] (or at least was - maybe they've fix
Single statements are not atomic! (Score:2)
Re:Use the right tool (Score:3, Insightful)
Really when are people going to get over this multithreading problem? Concurrency issues have been around for years with plenty of solutions for those who bother to learn about the principles.
While the parent poster mentioned Tanenbaum's Minix book with his tongue in his cheek, I think it's actually a very good introduction. "Principle
Re:Use the right tool (Score:2)
There are many ways to attack the problem true, but it remains a very difficult thing to do..
Especially for 'normal' programs say a game engine which must be changed quickly because of a new idea, that is to say not 'multiplying two matrices' types of programs.
Re:Use the right tool (Score:2)
Currently it is Software transactional memory (STM), the hot topic (see
http://en.wikipedia.org/wiki/Software_transactiona l_memory [wikipedia.org] ), it remains to be seen if it will be really useful..
That said, even currently even normal SW projects are difficult, concurrent projects are harder to make, much harder to debug, plus exploiting efficiently concurrency needs to be aware of the number of core: now your software must run efficiently on
Re:Use the right tool (Score:2)
I see alot of screwed up code because the coder did not understand the basics (granted the old/n
Re:Use the right tool (Score:2)
It is most definitely not the right tool if you want to do anything outside the java VM. Sun seems to feel that their language should represent the lowest common denominator of system level functionality across all operating systems. Unfortunately that means that if you want to do anything at the system level you'll have to work around fundamental limitations in Java. And the m
Re:Use the right tool (Score:3, Informative)
Re:Use the right tool (Score:2)
This is nonsense. Java has no per-thread cache of variables. I don't even know what you are misdescribing. I can only guess that it's one of these things:
Re:Use the right tool (Score:3, Interesting)
Not even that, actually.
In C, it tells the compiler that the read or write to memory can't be reordered. If you do a read, it has to get it from memory right then, rather than reusing one from before that it might have stuck in a register. It doesn't tell the CPU anything about synchronizing its cache or executing the instruction in order, however. You've gotta have both.
In Java, it actually depends on the version of the
Re:Use the right tool (Score:2)
Java is such a great langange it really pisses me off
Re:Use the right tool (Score:2, Interesting)
Does this article have any useful info? (Score:2, Informative)
Re:Does this article have any useful info? (Score:2, Funny)
All good programmers... (Score:5, Funny)
Re:All good programmers... (Score:3, Funny)
Go crazy?
Don't mind if I do!!!
Re:All good programmers... (Score:2)
The voices in my head jus told me I'm perfectly sane.
Multi-threaded Programmation Makes Me Crazy? (Score:4, Funny)
Re:Multi-threaded Programmation Makes Me Crazy? (Score:4, Informative)
Notice also: take a deep *breathe*.
But I agree... multi-threaded programming can drive people crazy. Message passing-based programming is less prone to nastiness than shared-state concurrency. (Languages like Erlang come to mind).
http://en.wikipedia.org/wiki/Concurrent_programmi
http://www2.info.ucl.ac.be/people/PVR/bookcc.html [ucl.ac.be]
You can also do Erlang-style message passing in Python using Candygram
http://candygram.sourceforge.net/ [sourceforge.net]
Re:Multi-threaded Programmation Makes Me Crazy? (Score:2)
Re:Multi-threaded Programmation Makes Me Crazy? (Score:2)
Firstly, I had no intention of chiding anyone. I was merely giving information.
"Notice also" is another way of saying "Please note also" and "take a deep breathe" was an verbatim quote from the original post (which has si
Re:Multi-threaded Programmation Makes Me Crazy? (Score:5, Funny)
Re:Correct grammer and word choice drive you crazy (Score:2)
Keep your mind to yourself, please.
Link to the home page would be nice (Score:5, Informative)
Re:Link to the home page would be nice (Score:2)
I agree that a spellchecker is not the end-all of looking for mistakes (their vs. there and so on aren't caught), but for the developers of the project to put "developper"
Re:Link to the home page would be nice (Score:2, Funny)
Here is there?... then where is there?
Here?
What happened to there?
Who's on first?
Re:Link to the home page would be nice (Score:2)
Five words... (Score:2, Funny)
These words are fillers.
Re:Five words... (Score:2)
-Rick
Probably going to download it anyway... (Score:4, Interesting)
Looking at the list of functions that it hooks into, I don't see pthread_rwlock*. Are the pthread_rwlock functions implemented using other pthread_* funcs? I haven't run into any problems yet with the project I'm working on, but it would be nice to run through this and make sure everything's working as expected.
May I be the first to ask... (Score:2, Insightful)
More Info on the Home Page? (Score:2, Insightful)
Not sure why they didn't link directly to it?
Bah (Score:3, Informative)
The only good general advice about learning how to develop software on distributed systems I can give is: Read some of Andrew S Tanenbaum's books about operating systems and distributed systems in particular. The books contain knowledge you'll be able to apply to almost every system you develop software for.
Why all the negativism in the posts? (Score:5, Insightful)
Come on.... (Score:2)
Re:Come on.... (Score:2)
Sorry, someone else is looking at them. You'll have to wait until later.
Re:Come on.... (Score:2)
Threads considered harmful... (Score:2)
Re:Threads considered harmful... (Score:2)
Multithreaded Haiku (Score:3, Informative)
Here's your problem... (Score:2)
Here's your problem. Shared state/variables is the anathema of good concurrent programming.
Here's a good place to start if you want to learn a better way...
http://www2.info.ucl.ac.be/people/PVR/bookcc.html [ucl.ac.be]
Re:Here's your problem... (Score:3, Interesting)
http://en.wikipedia.org/wiki/Concurrent_computing [wikipedia.org]
http://en.wikipedia.org/wiki/Message_passing [wikipedia.org]
http://en.wikipedia.org/wiki/Actor_model [wikipedia.org]
The E lang has some good documentation on concurrency, even if you don't use it.
http://www.erights.org/elib/concurrency/ [erights.org]
As does Erlang.
http://www.erlang.org/download/erlang-book-part1.p df [erlang.org]
Re:Here's your problem... (Score:2)
Re:Here's your problem... (Score:2)
Re:Here's your problem... (Score:4, Informative)
Your point that message passing is generally a cleaner design choice is valid, but it's not always a practical option.
Re:Here's your problem... (Score:2)
if 'messaging' is a compile-time abstraction rather than a runtime library, then this copy only needs to be made if the caller maintains a reference to the data and may mutate it afterwards. think of it is compile-time cow. this property of 'linearity' (bad term) is very helpful in composing abstractions, but it doesn't need to cost.
it's helpful to disambiguate the processor-visible data sharing model from the programming model. the
Re:Here's your problem... (Score:2)
Re:Here's your problem... (Score:2)
and no, i'm not talking about MPI, which is basically imposssible to get any kind of static niceness out
Re:Here's your problem... (Score:2)
That would be naive, so it's a good thing I did not say that. My point all along has been about granularity of exploitable parallelism, and that shared memory parallelism allows you to exploit a finer granularity. I said nothing about scalability. It's not always true, but in general, the finer the granularity you try to exploit, the less scalability you're going to get
Re:Here's your problem... (Score:2)
but the interaction between grain size and the shared memory/message passing paradigms is much weaker than you suggest in theory. of course if you're talking about marshalling messages over ethernet clusters then i have to agree with you.
Re:Here's your problem... (Score:2)
Re:Here's your problem... (Score:2)
Re:Here's your problem... (Score:2)
Bingo. It has to do with the granularity of parallelism. You can take a look at this paper written by people I work with, Multigrain Parallel Delaunay Mesh Generation: Challenges and Opportunities for Multithreaded Architectures [wm.edu]. But understanding why is simple: if the cost of communication overwhelms the gain from doing the
valgrind used to be able to do this (Score:3, Insightful)
personally, i can't say enough good things about valgrind. there are a couple non-obvious issues (support for sse/sse2/sse3 is still in the works, so if you get an inexplicable SIGILL, this is probably the problem), but it's saved me hundreds of hours over the past year (and i'm sure it'll save me even more in the future).
that all said, my (admittedly limited) experience with threading is that it's best to design the deadlocks away before you even touch the editor. i wonder if there are any design tools which support deadlock / contention checking at the model or design level?
No that's just common sense. (Score:3, Insightful)
That's not "limited" experience. That's common sense. Trying to find deadlocks, race conditions, and accidental serialization in an application by experimentally compiling and running is like trying to build a house by nailing the boards together only after they've collapsed on you.
Seriously, threads cannot be bolted on as an afterthought. You have to consciousl
Re:valgrind used to be able to do this (Score:3, Informative)
At my previous company we built a system with on the order of 10 threads working on a combined dataset consisting of many hundreds of thousands of objects and occupying a couple hundred meg of memory in a large installation. There could be hundreds of thousands of instantiated locks in the system, although they fell into maybe 30 classes of lock. The large number of objects and locks was manageable because there were a small number of objects (say on the order of 25) that modeled something in the real world
Monitors (Score:2)
Googling doesn't get me a good link to post, but I know it's a common concept in multithreaded programming and has always worked f
How Ironic.... (Score:3, Interesting)
Developers: Multi-threaded Programming Makes You Crazy? 79 of 78 comments
What's wrong with this picture?
Explanations... (Score:3, Informative)
Firstly, I apologize for my English (I'm doing my best).
I perfectly agree with some of you: this article is a slashvertisment! The main reason for that is that I previously tried to submit something more descriptive, but it was rejected. That's why I tried again with a slightly different style.
This tool [sourceforge.net] (PTT) inserts trace points into the NPTL to help you to analyze multithreaded applications behaviour. He's not designed for beginners, but for people facing complex multithreaded issues. I also agree with some of you: you can use Java or some others high level languages for programming. But some applications require performance and have to be written in C. That's why PTT can be useful for some developers.
PTT has been presented at the Ottawa Linux Symposium last summer. You can find the paper here [linuxsymposium.org] (NPTL Stabilization Project, page 111).Regards...
Tailor a concurrency model for your application (Score:3)
The most popular way is to create a workflow model with task queues, worker threads, and job dependencies, plus a few application-specific rules to ensure that resource limitations don't cause deadlock.
The high-level model can typically be lifted right out of your proof of deadlock avoidance. Don't have one of those? It's a good idea. The proof gives you a minimal solution and confidence to implement it. Without the proof, you're going to overkill the problem out of nervousness, and you still might miss something crucial.
notifyAll() (Score:2)
Java's implementation of Monitor does not have wait conditions -- there is only a generic wait() and a generic notify(), and then you have to set and test variables inside synchronized blocks to figure out what you are notifying for and waiting on.
notify() only wakes up a random thread, so if you have multiple threads waiting, each waiting thread should notify() upon coming out of a wait() so that other threads get served, or you
Re:notifyAll() (Score:2)
The only downside to this is that you can't wait on multiple objects, but the ne
Re:notifyAll() (Score:2)
In fact, it is probably (though not necessarily) a design error unless every single waiting thread is in exactly the same piece of code in exactly the same state, so it doesn't matter which one is woken up. If you have different threads waiting on different conditions, they should be using different objects to do the waiting. If you have a bunch of threads and always want to just wake up one specific one, then have an object per thread. Depending on the program logic, you may even be able to just use a s