Multi-threaded Programming Makes You Crazy?
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. "
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 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!
Javascript + Nintendo DSi = DSiCade
It looks like it's just a link to a sourceforge project... was there supposed to be something else?
dennis
Are a little mad anyway ;)
Our greatest enemy is neither a single man, nor is it a nation, it is, as it has always been, our own greed.
I was expecting a bit more substance to the article than something that sounds like it came from a (bad) marking department (what's a "deep breathe" anyway?), and a link to some sourceforge project.
What's going on?
No, this title does. Is a Sentence? Is a Question? Why There a Space Before the Question Mark? What 'Programmation'?
I was wondering what was this program was about. Fortunately, here is there website. http://nptltracetool.sourceforge.net/
Ooo man the floppy drive is broken. No wait. The computer is just upside down.
Slashvertismentation.
These words are fillers.
"Correct grammer"
Heh. :P
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.
<xml><I><am><so><damn>Web 2.0</damn></so></am></I></xml>
Take a deep "breathe"?
...what's so original about this issue, that deserves to be posted to Slashdot? There isn't even a FA! If the guy wanted to publicize his work (he is a developer for the linked SF project), he could at least have written an article with a concrete problem (even if the problem was made up in order to show the solution), not just some generic rant about how tricky multithreaded "programmation" is.
You can probably get a better idea of the purpose of the program on their home page (click the link in the menu of the sourceforge page that says, "Home Page").
Not sure why they didn't link directly to it?
Java's "builtin thread saftey" is simply a poor hack. The idea is to give _every_ structure a mutex. Any access to the structure requires a mutex lock.
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).
Aha, so I can only do multithreaded programming on GNU/Linux with NPTL'ed glibc or what? Other programming langunguages than C/C++ don't exist or don't do threading. What about other operating systems? Specific solutions to general problems only apply to specific manifestations of the general problem and are therefore useless for most of us.
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.
Developing multithreaded is infact difficult, and any tool claiming to make it easier is worth looking at. If it works, these guys have done us all a favor. If it doesn't, at least they've made an attempt, and it may inspire others to do improve on it. Better tools are always welcome.
Generally, bash is superior to python in those environments where python is not installed.
No screenshots???!!!!
I have found there are just two ways to go.
It all comes down to livin' fast or dyin' slow. -REK, Jr.
Moshe Zadka said it better than I ever could.
If you reply, do so only to what I explicitly wrote. If I didn't write it, don't assume or infer it.
I got several concurrent threads that write the same variable!
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
"It is better to die on one's feet than to live on one's knees." - Albert Camus
http://valgrind.org/ used to include a tool called hellgrind for finding just such problems. unfortunately, hellgrind has gone away for a bit (it broke when the VM was re-done to support non-x86 platforms), but julian & co are working hard to get it working again Real Soon Now (tm). if you're using x86, you can use an old release of valgrind (2.2.0 i think) and you should be fine.
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?
Man, I wish I still had mod points to give you.
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 multi-threading capabilities. To me, the biggest difference was C versus Pascal style syntax. I guess the other big difference is the JVM.
I haven't used Ada or Java enough recently to know too much about their relative merits. But it seems to me that Java doesn't give us a whole lot more than Ada had about 10 years earlier.
Software sucks. Open Source sucks less.
No thanks, I think I'll go loose my mind instead.
;)
Keep your mind to yourself, please.
Arguing about vi versus Emacs is like arguing whether it's better to make fire by rubbing sticks or banging rocks.
Single statements in Java are not atomic. You should use locks even on single statement operations. There is no guarantee that you won't get interference, otherwise.
I always use a monitor class with multithreaded programming; the class handles all the synching and nothing is shared between the threads. In essence, the monitor is a singleton and each thread makes a call to something like g_monitor.getwork(&work) and inside getwork() I do (in pseudocode) wait on mutex, get mutex, pop work off queue, release mutex, hand work back to caller.
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 for me...I have never encountered a race condition or a deadlock and I've used this on some pretty intense server apps.
Just my $0.02.
Don't you just hate it when people reply to your signature?
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.
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 consciously design threads in in the first place, and if you ignore this advise and attempt to retrofit your code, then you must audit the code fully first to see where execution can be grouped into the smallest safe units for locking.
I've seen what happens when you ad hoc threading in large library that was never designed to be reentrant. Worse, I've seen what happens when you get it working on Windows but fail to realize that the UNIX version never was successfully locking the library for 3-4 years before a customer tried to build an aggressively multithreaded app on top of it and only then discover all the deadlocks that lay hidden inside.
If it's for-profit but free, you're not the customer -- you're the product (e.g., the Slashdot Beta's "audience").
It's all about OCCAM!
M0571y H@rml355.
Oh man - blast from the past, big time! We used Transputers at GEC Alsthom for ages. Occam2 was actually my first industrial-level language, rather than C (which I learnt at uni but then didn't use for a couple of years). Eventually Inmos tanked, the supply dried up (GEC bought practically all the remaining stock to keep them in spares) and we had to start again with a new platform and RTOS.
Shame really. Transputers were a great bit of kit, just underfunded, over-expensive and too far ahead of their time.
Grab.
Slashdot reported the summary line thusly:
Developers: Multi-threaded Programming Makes You Crazy? 79 of 78 comments
What's wrong with this picture?
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 (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 (NPTL Stabilization Project, page 111).Regards...
A debugger won't help you if you're trying to ensure correctness at too low a level of abstraction. Most languages give you a couple of low-level building blocks equivalent to the pthreads basics: threads, mutexes, and condition variables. These should not be used directly except in the simplest of circumstances. Rather, they should be used to create a set of higher-level tools that can be applied in a simple and straightforward way to your task.
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.
Read this book: Concurrent Programming in Java: Design Principles and Patterns by Doug Lea. It's a bit dry, but well worth the read. Even if you're not programming in Java, the concepts, problems, and solutions are similar. Java just offers some abstraction.
Understand the primitives, wait(), notify(), synchronized. Then learn Java 1.5's java.util.concurrent package, so you won't have to use wait/notify yourself in most cases.
Most programmers don't understand the issues that come up with concurrent programming, and if you can learn them, it's yet another way to set yourself apart. They used to teach this in operating systems class, but these days, who knows.
it seems to me that Java doesn't give us a whole lot more than Ada had
How about a runtime you can use on a cell phone?
Just junk food for thought...
It's not difficult to crosscompile an Ada compiler for embedded chips like ARMs and Xscale. This generally lacks certain featuers (ie, real time and threading)... but this is pretty trivial to get most of GNAT up and running on a major processor.
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'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 need to use notifyAll(). notifyAll() is like I made an unclear question on an exam, and I have to announce during the exam a change or correction, and 100 heads bob up at once in response.
You see, I can't direct a notify() to a particular wait() -- I have to notify() one at random or notifyAll() and have each wakened thread check condition variables to see if they were the target of the notify. I am not even sure if notify() works correctly in an app with only one wait() in it because there may be other threads in the GUI or wherever that are doing a wait().
And those libraries don't help because they are built on top of notify(), notifyAll() and wait().
Thus spake the Assembler programmers of the first C compilers . . .
. . . and the C programmers of the C++ compilers . .
. . . and the C++ programmers of Java . . .
This is all just my personal opinion.
Take a look at java.util.concurrent (as another response has suggested). Specifically, look at:
2 SE/concurrency/index.html
e ncy/overview.html
y /j-csp1.html
;-).
"Concurrent Programming with J2SE 5.0"
http://java.sun.com/developer/technicalArticles/J
and
"Concurrency Utilities Overview"
http://java.sun.com/j2se/1.5.0/docs/guide/concurr
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 want to look at some other frameworks that have been created in Java, such as CSP, covered in a series of DeveloperWorks articles beginning with:
"CSP for Java programmers, Part 1"
http://www-128.ibm.com/developerworks/java/librar
There's a lot out there to let you think in much higher-level concepts than simple locks (although you can do that to, for the learning exercise
The reason Java runs on a cell phone is not that Java has a small footprint. It's because the computers inside cell phones are a lot beefier than they used to be. I used Ada on a 32-bit VAX system that was running at less than 100 MHz and had (I think) 32 MB of RAM. Today's cell phones are around that same magnitude of processing power.
Software sucks. Open Source sucks less.
What , you mean like a Java compiler and JVM for example?
Or did you think they were written in Java (which in turn
was written in java etc, turtles all the way down)?
Thanks for the input, I learned a lot from the discussion. I was under the impression that wait() was this big party-line affair where you couldn't notify a particular wait. Since notify() and wait() are object-monitor specific, that solves the problem I thought I had.
But in online discussions of notifyAll(), there is a lot of talk of how notifyAll() is so very necessary yet inefficient when you have lots of threads -- I haven't seen any discussion of using a separate synchronized object for every wait that you want to do, allowing use of straight notify().
I18N == Intergalacticization
I too remember Transputers and they were way too expensive and didn't keep up with performance. Eventually I found that serial processing on a 25 MHZ 386 could take the load of around 5-8 of them. After that a bit of funky coding using networked files blew them away for a fraction of the cost.
if you can so so then its a good idea to develop on a dual CPU box. That way you will catch bugs much much earlier.
note: i'm known as plugwash most places but i screwd up registering that here somehow in the past and now can't register