[jmm-dev] Atomic references
ludwig.mark at siemens.com
Sun Feb 9 07:33:37 PST 2014
This is probably in the category of "picking a nit," but I have yet to find any statement that shared Java variables that are object references are atomic. (An example of a shared variable is a class static declaration.)
That is, I have the impression that a shared variable that is a reference to an object (these days, a 4- or 8-byte pointer at the hardware level for 32- or 64-bit architecture, respectively) is naturally atomic, that if I have two or more asynchronous Java threads assigning an object reference to a shared variable, or assigning null to a shared variable, that any other thread reading that reference will consistently read either null or one of the object references assigned along the way.
We believe this is true because of the need for such atomicity within the hardware, so it naturally provides this in the machine instructions that store and retrieve addresses (between registers and main memory). This assumption might only hold for properly-aligned values in main memory, but we assume that Java provides this at the machine level, naturally, too. ("Properly aligned" means that any address referring to a 4-byte address in memory has zeroes in the last two bits, and an 8-byte reference has zeroes in the last three bits.)
To be clear, I am /not/ talking about an 8-byte /anything/ on a 32-bit architecture. I am also aware that, without synchronization, there is a timing window among the threads about what they read (that any thread may read out-of-date data for an indeterminate period of time according to the hardware caching architecture). My point is not about timing, per se, but about self-consistency among the bytes comprising a reference in a shared variable.
We use this assumption heavily in a server application, and have yet to ever hear of any trouble or concern around this, but cannot find anything specifying this behavior. While all you distinguished folks are updating the JMM, I thought you might cover this. OTOH, if it /is/ specified, I'd appreciate a pointer to the language specifying it.
For background - and in case I haven't used terms above that precisely mean what I intend:
We use this technique for letting threads allocate a Singleton, with an idempotent construction sequence, that is accessed at very high frequency, without using any synchronization. (Each thread looks for null and if it is, constructs the Singleton and assigns the reference.) This makes sense to us when the code to construct the Singleton is cheap enough, and we have strictly limited the Singleton to final fields in order to use the existing JMM guarantee that when construction finishes, it's safe to let any thread pick up a reference to the object and use it asynchronously. I use the label "very high frequency" when accesses to the Singleton occur within each thread perhaps thousands of times per second on a fast-enough machine. We believe it's cheaper to let every thread (at the worst case) construct the Singleton, and let the garbage collector take care of cleaning up the duplicates (if any), than it would be to synchronize around the reference for the life of the application.
The server application runs for indeterminate periods of time ... easily months, depending on scheduled down-time. It creates threads for client actions. (We write business software in use by an unknown number of customers.) At large customer sites, easily millions of threads go through this code while the application is running. Such sites have large processor complexes. We know one customer has 64 processors in a large server machine.
The fact that threads are created to service client requests also means that the number of competing threads during application start-up is limited to a fairly small number. I would be surprised if any customer could manage to get even ten (10) client actions running concurrently that might all construct the Singleton. At the peak of the working day, once there are thousands of users sending requests to the server, it's reasonable to expect that every processor is reading the reference to the Singleton perhaps thousands of times per second. (We know from scalability testing that synchronizing around such a reference imposes a noticeable bottleneck.)
Product Lifecycle Management
Siemens Industry Sector
Siemens Product Lifecycle Management Software Inc.
5939 Rice Creek Parkway
Shoreview, MN 55126 United States
Tel. :+1 (651) 855-6140
Fax :+1 (651) 855-6280
ludwig.mark at siemens.com <ludwig.mark at siemens.com%20>
More information about the jmm-dev