Выбрать главу

Seibeclass="underline" So Java provides, as you say, building blocks that let you get portable access to threads provided by the OS and then some higher-level constructs with the java.util.concurrent API. But they’re still pretty lowlevel constructs compared to something like Erlang or STM, aren’t they?

Bloch: I’m not so sure. Some of Java’s building blocks are low-level, like AtomicInteger; some are midlevel, like CyclicBarrier; and some are highlevel, like ConcurrentHashMap and ThreadPoolExecutor. I believe that STM and actors could both find comfortable homes in Java’s “concurrency building blocks” approach when and if people are convinced that they pull their weight.

Some form of transactional memory may become important in the future, perhaps as a building block for use by concurrency library designers. But I don’t think STM will succeed as a tool that lets the application programmer stop worrying about locks and live in a beautiful world where threads don’t interfere with one another. It’s just not going to happen.

There are a bunch of reasons for this. Here’s one I learned when I worked in transaction systems. When you try to do automatic locking or optimistic concurrency control based merely on reading and writing at the byte level, you end up with “false contention” between threads: you have physical conflicts that don’t correspond to logical conflicts. If you’re forced to think about what locks to acquire, you can do your best to ensure that you don’t acquire any locks beyond what is required to enforce logical conflicts.

So, for example, if you have two threads, both of which are incrementing a counter, they should be allowed to proceed concurrently. They may be accessing the same piece of memory but they’re not conflicting with each other from a logical perspective. If you have one thread that’s reading a counter and one that’s incrementing it, they’re in conflict. But you can have arbitrarily many readers or arbitrarily many incrementers proceeding concurrently. This is the sort of thing that no system that I’ve seen to date can figure out of its own accord. The counter example may be artificial, but it’s not uncommon that physical contention is far more restrictive than logical contention.

Another problem with STM is that there are all manner of operations that can’t occur inside a transaction. I/O is the classic example. A third problem is that some STM schemes allow “doomed transactions” to view memory in inconsistent states, with potentially disastrous results. Again, these are problems that we struggled with back when we were building generalpurpose distributed transaction systems. They have solutions, but all the solutions I know of add complexity or reduce performance.

Anyway, to the best of my knowledge, STM is still research. I think it’s great that people are doing this research. But I simply don’t believe in a silver bullet for concurrency, at least for the foreseeable future.

Seibeclass="underline" OK, different topic: how do you prefer to work with other programmers?

Bloch: I’m actually quite flexible. I love “buddy programming” where you’re working with someone else but not at the same keyboard. You’re writing different parts of the system—you trade the code back and forth. You don’t even have to be in the same hemisphere. Doug Lea and I have worked that way extensively over the years. One of us will write an interface and the other one will say, “Well this is great but this part sucks and I changed it this way.”

Eventually we arrive at some interface that we like and I’ll implement the nonconcurrent version and he’ll implement the concurrent version and as we do that, we’ll find out all the things that we did wrong and take another crack at the interface. And we’ll read each other’s code and he’ll say, “Well, you can make this much faster this way,” and I’ll say, “You’re right, Doug, you can.” He’s very good at making things go fast—he kind of communes with the VM. So that’s one style that I like a lot. And that lends itself to remote collaborations.

I do like sitting at the same terminal with someone and working on code, but I haven’t written many programs that way from the ground up. Typically it’s in the context of a code review where I’ll get some code to review and there’ll be a lot of changes and I’ll say, “Why don’t we just sit together at a machine and bash it into shape?” That’s good for a whole bunch of reasons. I think it’s a great way to teach, to pass knowledge down from one generation of hacker to the next.

I don’t like working in total isolation. When I’m writing a program and I come to a tricky design decision, I just have to bounce it off someone else. At every place I’ve worked, I’ve had one or more colleagues I could bounce ideas off of. That’s critically important for me; I need that feedback.

Seibeclass="underline" Is that for the feedback you get or just for the chance to talk it through?

Bloch: Both. There’s so much craft in what we do—it’s often the case that there’s no one right solution, or if there is, it’s not apparent until you’ve used it. You have to go from the gut and talking to someone with a different perspective can be very helpful.

I’ve known people who don’t feel this way—who are willing to program in a vacuum. I think it hurts them. You will discover your bugs earlier—you really want to discover problems with a design long before it hits the point of code. So when you’re wrestling with different approaches or even different features—should I support this and this or simply that—you just have to bounce it off other people. On the other hand, you can’t take what each person says as gospel because you’ll get conflicting opinions, and ultimately, you are responsible for your own work.

Seibeclass="underline" That raises another age-old question—I think Weinberg wrote about this in The Psychology of Computer Programming in the ’70s and the XPers talk about it today: should code be “owned” by one person who is the only person who ever touches it or should everyone on a project collectively own all the code so anyone can fiddle with anything?

Bloch: I believe that code ownership can’t be denied. In a way, it’s like motherhood—you give birth to the code that you write, and especially if it’s large, complex, or original, it is yours. If you find yourself working in someone else’s code, talk to them before mucking with their code. Especially if you think there’s something really wrong with it, because you might be wrong. If you break someone else’s code, that’s not nice.

Of course, it’s bad for an organization if a piece of code belongs to exactly one person because if that person leaves the organization, they’re high and dry. So it’s really important that multiple people learn about each piece of code and are able to work on it. But I think it’s unrealistic to expect everyone to own all the code.

This also touches on what we were discussing earlier in terms of areas of expertise. There aren’t that many people who can really write bit-twiddling code, so if you find yourself in the bowels of some code that’s doing bit twiddling, you should talk to one of the few people at your company who can actually handle that stuff, if you’re not one of them. People who do this stuff love it and are willing to spend whole days reducing an instruction sequence by one instruction or proving some identity that speeds up a computation. But it’s so easy to break something. And it’s so easy to write something that, let’s say, works well for 232 minus 1 of the 232 possible inputs. A unit test may or may not test that one value where your new solution doesn’t work. And if it doesn’t and you broke it, you’re the goat.

Seibeclass="underline" Speaking of writing intricate code, I’ve noticed that people who are too smart, in a certain dimension anyway, make the worst code. Because they can actually fit the whole thing in their head they can write these great reams of spaghetti code.

Bloch: I agree with you that people who are both smart enough to cope with enormous complexity and lack empathy with the rest of us may fall prey to that. They think, “I can understand this and I can use it, so it has to be good.”