Skip to main content

Posts

Volatile Arrays in Java

I get asked a lot about how the volatile keyword interacts with arrays, so it is probably worth a blog post on the subject. Those of you who have read my posts on volatile ( Volatile Fields and Synchronization , Volatile Does Not Mean Atomic and, most importantly, What Volatile Means in Java ) will have a pretty good idea of what volatile means, but it is probably worth it to provide a reminder. Basically, if you write to a volatile field, and then you have a later read that sees that write, then the actions that happened before that write are guaranteed to be ordered before and visible to the actions that happen after the read. In practice, what this means is that the compiler and the processor can't do any sneaky reordering to move actions that come before the write to after it, or actions that come after the write to before it. See my post on What Volatile Means in Java for more detail. With that out of the way, let's go through some examples of what you can do with vol...

Welcome!

Mailinator's Paul Tyma linked to me . If you are following from that link, the relevant blog entry you are looking for is probably this one, specifically, the entry labeled "visibility" .

Faster Logging with Faster Logger Classes

Today, I'll discuss a little tweak I made to java.util.Logging that made my logging throughput double. I want to use it as an illustration that it often isn't very difficult to improve the performance of concurrent code by doing things that are actually pretty easy to do. So, "I" have an application that is running a couple of hundred threads on an 8-core machine, and it wants to log about 2MB a second using java.util.Logger . When I say "I have", I actually mean "someone else has", because if "I" had to log a megabyte a second, there is no way I would use java.util.Logger to do it. Still, we all make our choices. When I came to this code, it was already doing sensible things like buffering its output. It wasn't doing something more complicated, like using a dedicated logging thread. It could log about 1MB a second, and was chewing through CPU pretty rapidly. I just decided to run our profiler on the code and see where the bot...

Small Language Changes for JDK7

For those who haven't been paying attention, there is a new project from Sun to attract proposals for small language changes to JDK7 . Even in the first day of open calls for proposals , the entries have been very interesting: Strings in Switch, a proposal from Joe Darcy to be able to use Strings in switch statements. Automated Resource Blocks, a proposal from Josh Bloch to be able to say things like: try (BufferedReader br = new BufferedReader(new FileReader(path)) { return br.readLine(); } instead of: BufferedReader br = new BufferedReader(new FileReader(path)); try { return br.readLine(); } finally { br.close(); } based on having BufferedReader implement a Disposable interface. Block expressions, a proposal from Neal Gafter to be allow things like: double pi2 = (double pi = Math.PI ; pi*pi)**; // pi squared* Basically, the principle here is that the (parenthesis-delimited) block would return a value. Exception handling improvements, another proposal from Neal Gaft...

Date-Race-Ful Lazy Initialization for Performance

I was asked a question about benign data races in Java this week, so I thought I would take the opportunity to discuss one of the (only) approved patterns for benign races. So, at the risk of encouraging bad behavior (don't use data races in your code!), I will discuss the canonical example of "benign races for performance improvement". Also, I'll put in another plug for Josh Bloch's new revision of Effective Java (lgt amazon) , which I continue to recommend. As a reminder, basically, a data race is when you have one (or more) writes, and potentially some reads; they are all to the same memory location; they can happen at the same time; and that there is nothing in the program to prevent it. This is different from a race condition , which is when you just don't know the order in which two actions are going to occur. I've put more discussion of what a data race actually is at the bottom of this post. A lot of people think that it is okay to have a data...

What Volatile Means in Java

Today, I'm going to talk about what volatile means in Java. I've sort-of covered this in other posts, such as my posting on the ++ operator , my post on double-checked locking and the like, but I've never really addressed it directly. First, you have to understand a little something about the Java memory model. I've struggled a bit over the years to explain it briefly and well. As of today, the best way I can think of to describe it is if you imagine it this way: Each thread in Java takes place in a separate memory space (this is clearly untrue, so bear with me on this one). You need to use special mechanisms to guarantee that communication happens between these threads, as you would on a message passing system. Memory writes that happen in one thread can "leak through" and be seen by another thread, but this is by no means guaranteed. Without explicit communication, you can't guarantee which writes get seen by other threads, or even the order in whic...

G1 Garbage Collector in Latest OpenJDK Drop

ETA: The G1 collector is now in the latest JDK6 release, which you can download from Sun here . You can enable it for testing with the flags -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC . Original post follows. For those of you who are interested in tinkering with new garbage collectors, the "Garbage-first" G1 garbage collector is in the new JDK7 drop from OpenJDK . I haven't tried it yet, but I am looking forward to seeing what it does. (You will notice the link doesn't say anything about the new GC. Here's the appropriate bug .) G1 is supposed to provide a dramatic improvement on existing GCs. There was a rather good talk about it at this year's JavaOne. It allows the user to provide pause time goals, both in terms of actual seconds and in terms of percentage of runtime. The principle is simple: the collector splits the heap up into fixed-size regions and tracks the live data in those regions. It keeps a set of pointers — the "remembered set...