I bought this book because of the "Testing and Debugging" in the sub-title as this is an area that other books on multi-threading tend to skip.
About the book - four negatives first, but do read the positives afterwards as well as they are big positives...
The first thing that hit me (and this is the least significant, but one for the publisher to be aware of) when reading this book was how old-fashioned it looks. For a book called "Modern Multithreading" you would think that Wiley (the publishers) would have presented the book better. The drab brown cover doesn't really matter, but the formatting of the text inside does. Source listings are shown in the same typeface as surrounding text, with no border etc to differentiate them. Worse is that if the text refers to a listing, the listing is likely to be on the next page wrapped in text about something else. The whole presentation is really poor.
The second thing that hit me, which is more significant, is that the authors simply do not write well. There can be no doubt that the authors are academics and that this book is a text book - it is not an easy read (because of writing style, not difficulty of content) and comes across as being a bound version of all of the photocopied hand-outs that you can imagine being given out at lectures during a computer science degree course. If you think of hand-outs as being notes that are typed up to support what was said during the lectures then you can imagine how they read. Put over 400 pages of them together and you get a feel for this book. Terse (but worth persevering).
The third negative, is that the code samples are described by the authors as a library, but they are not seriously useable as such. Maybe we've been spoilt by some of the excellent C++ and Java books that have been produced over recent years, but it has become common to be able to lift useful bits of code from books and reuse them without change. The code in this book is not like that. Good for research but not for serious use without being reworked. I have downloaded the full source code from the author's web-site (it doesn't all appear in the book) and found that for serious use it (a) needs some bugs fixed, (b) needs better error handling, (c) need optimising, (d) needs general reworking (it wouldn't pass code review the way it stands).
Fourthly, the index is incomplete and there is not a glossary. Why is this a problem? Well, given how difficult a read this is you can imagine how easy it is to glaze over. I clearly did that somewhere as I missed the meaning of an abbreviation that was then used repeatedly later on. I must had seen that same abbreviation used half a dozen times before thinking that I really should find out what it means as it seemed to be getting increasingly significant. I looked for a glossary but there isn't one included. I looked in the index to find the first page the abbreviation was used. Unfortunately the index didn't list the first page it was used, so I ended up scanning all the way from the start of the book to find the meaning. I'm very glad to have found it, because the moment I did the whole intention of the book started falling into place (although that wasn't confirmed until more than 140 pages in - see below).
Now for the plus points - well, one anyway...
This book covers something I have never seen any other book attempt to do. Most books say something along the lines of "multi-threading is hard, testing and debugging multi-threaded programs is really difficult and we're not going to give you any advice about how to do it". Well not this book. You may need to get more than 140 pages into the book before it reaches the really interesting ideas, but this book attempts to explain how to trace the interactions between different threads and to provide a way of replaying the same sequence in order to test/debug problems. As well as that it gives methods that will help to identify race conditions and deadlocks (where most books describe what they are and then go no further). Given that pre-emptive multi-threading gives you a system that is inherently non-deterministic, to attempt to provide repeatability by building a layer over the usual synchronisation mechanisms is a really interesting idea. It slows your code down so you don't want to put it into production code (another change required to the code), but during development it could be really handy. It doesn't give you a completely deterministic system, but helps to make the main interactions between threads more repeatable.
So to summarise - a couple of very interesting ideas that are incredibly badly presented, but given that I have never seen any other book try to describe the same material I'm afraid that there is no better book to recommend (please tell me if there is!). I've started using the ideas presented in this book in my own code, fixing/enhancing the code from the book in the process. Given that getting this code into a "professional" condition is a non-trivial task, that should give an idea of how useful I think the ideas are. Its taken a couple of weeks to integrate into my own threading library, but tracing, race condition detection and deadlock detection are working, though the deadlock detection mechanism is pretty primitive - I may do further work on that to make it more useful. Although I have coded the replay mechanism I haven't tested that yet - will update this review with the result when I have time to test it.
If you are new to multi-threading buy something easier to read as a tutorial, but if you already have good multi-threading experience and want to build your own framework combine the material from this book, with ideas from "Programming with Hyper-Threading Technology" and (for Windows) details from "Programming Applications in Microsoft Windows".
[Note added April 2009] Intel sell a tool called Intel ThreadChecker which does detection of race conditions very successfully. Rather than add extra complexity in your own code to check for such issues, you may prefer to simply use ThreadChecker.