Warning! Threading in
a multiprocessor world - JavaWorld February 2001
Tutorial Details:
Warning! Threading in a multiprocessor world
Warning! Threading in a multiprocessor world
By: By Allen Holub
Find out why many tricks to avoid synchronization overhead just don't work
had intended this month to carry on with presenting a caching class loader -- that was the whole point of the zip-file access classes I presented in the last couple of columns. I've decided to digress for this month, however, on a threading-related issue that's important enough that I wanted to bring it to your attention sooner rather than later.
Double-checked locking can be hazardous to your code!
This week JavaWorld focuses on the dangers of the double-checked locking idiom. Read more about how this seemingly harmless shortcut can wreak havoc on your code:
"Warning! Threading in a multiprocessor world," Allen Holub
Double-checked locking: Clever, but broken," Brian Goetz
To talk more about double-checked locking, go to Allen Holub's Programming Theory & Practice discussion
This article discusses why a whole category of techniques that programmers misguidedly use to avoid synchronization overhead simply don't work. Probably the most common of those is double-checked locking, which I'll discuss in a moment. In a recent posting to a Java Memory Model mailing list, Bill Pugh at the University of Maryland (one of the folks who's spearheading the rewriting of the JLS (Java Language Specification) to compensate for some of the problems discussed this month) said, "...this double-check idiom is like a roach infestation. It doesn't matter how many of them you crush under your shoe, more of them crawl out from under the refrigerator." Well, I hope this article will help stamp out the swarm.
So what's the problem?
In the beginning, a CPU could write directly to memory simply by wiggling the voltages on a few wires that connected the CPU chip to the memory chip. All was well with the world. Even with multithreaded systems, only one path to memory existed, and reads and writes to memory always occurred whenever the CPU executed the associated machine instruction. The introduction of memory caches didn't fundamentally change that model (once they got the cache-coherency bugs worked out). Indeed, the cache is transparent to the program if it's implemented correctly. That simple memory model -- the CPU issues an instruction that modifies memory with an immediate effect -- remains in most programmers' minds.
Then somebody had the bright idea that two processors could run in the same box at the same time, sharing a common memory store (Suddenly, the world became much more complicated). In that situation, a given CPU can no longer access memory directly because another CPU might be using the memory at the same time. To solve the problem, along came a traffic-cop chip, called a memory unit. Each CPU was paired with its own memory unit, and the various memory units coordinated with each other to safely access the shared memory. Under that model, a CPU doesn't write directly to memory but requests a read or write operation from its paired memory unit, which updates the main memory store when it can get access, as seen in Figure 1. Those early memory units effectively managed simple read or write request queues.
Figure 1. The memory unit
Relaxed memory
All was well with the world until some bright engineer (I believe at DEC -- at least the Alpha, to my knowledge, was the earliest machine that worked like that) noticed a way to optimize memory operations with the hardware. Consider this code:
int a[] = new int[n];
int b[] = new int[n];
for( int i = 0; i < a.length; ++i )
b[i] = a[i];
The resulting read/write-request queue is shown in Figure 2. Our intrepid engineer said, "Ah ha! If I allow the memory units to shuffle around the order of pending read/write requests while they're waiting to get access to the main memory store (giving us Figure 3), then I can turn all these atomic moves into one big block move." That is, the memory unit can transform the requests in Figure 2 into the situation shown in Figure 4. That reordering strategy became known as a relaxed memory model.
Figure 2. Copying an array: the initial state
Figure 3. Copying an array: operations rearranged
Figure 4. Optimizing the array copy
"Oooooooh!" said our engineer, "now things are a lot faster."
"But, but, but," said the programmer, "now the order in which I write things to memory may not be the order in which the writes actually occur!" (More correctly, the writes might become visible in nonsource code order.)
"Well," said the engineer, "I hate to slow things down unnecessarily, but what if I give you a way to prevent requests from moving beyond certain well-defined boundaries, called memory barriers ? Requests issued between two memory barriers can be reordered, but no request can move past a memory barrier." (I'm simplifying a bit, since sometimes movement is possible, but that's the central concept.)
Figure 5 shows a couple of memory barriers. Requests are not permitted to migrate across the barrier. That way, at least we can guarantee that a write can occur before a subsequent read request is issued.
Figure 5. Memory barriers
So why do I care?
So why, you might ask, do I care about all that? The answer: programmers are too clever for their own good. They read how synchronized works: it goes out to the OS and acquires an exclusion semaphore (or mutex); an expensive operation, so too-clever programmers try to work around it. A classic too-clever example tries to leverage the fact that modification of a boolean is atomic. For example:
boolean is_okay;
long value;
void f()
{
if( is_okay )
do_something( value );
}
void g( long new_value )
{
value = new_value;
is_okay = true;
}
In the example above, the f() method is called from one thread, and the g() method is called from another. The problem is that, when the two threads run on separate processors, the modifications of value and is_okay are found within the same memory barriers and are therefore subject to reordering. The is_okay field can effectively be set true before the new value of value is available. (A note for the expert-level precision impaired: don't quibble with me about visibility versus actual modification -- the effect is the same.) Note that the reordering would not matter in a single-threaded situation, where g() would complete in its entirety before either value could be used.
Synchronize!
So what's a programmer to do? Synchronize! Figure 6 shows the situation when a synchronization occurs. When you dig deep enough into the bowels of the operating system, you'll find that releasing a mutex is effectively nothing but setting a flag, and acquiring a mutex is a loop (called a spin lock) that does an atomic-bit-test-and-set operation. (In one memory cycle, the instruction tests a bit in memory and sets it true if the result was false. The instruction simultaneously sets a machine register to indicate whether or not it modified the bit.) Most importantly, those operations are effectively surrounded by memory barriers. Looking at Figure 6, all the memory operations that occur on CPU1 (to the right of the memory barrier that surrounds the mutex release) must be visible in main memory before any read operations on CPU2 (to the left of the memory barrier that surrounds the mutex-acquire operation) can be executed.
Figure 6. Memory barriers surround synchronization
To summarize, synchronization implies a memory barrier. In that case, two exist: one barrier associated with entering a synchronized block or method and another associated with leaving it:
synchronized( xxx )
{ // code here is bracketed by memory barriers.
}
Consequently, though the code within the synchronized block is subject to reordering, all modifications made within that block will be visible in main memory (for other threads to view) when you exit the synchronized block.
The following code works just fine and is easier to understand than the earlier example to boot:
long value;
synchronized void f()
{ do_something( value );
}
synchronized void g( long new_value )
{ value = new_value;
}
With all that in mind, live by this rule:
The visibility of a memory modification is guaranteed only when the modifying thread releases a lock that is subsequently acquired by the examining thread.
Period.
No exceptions.
Ever.
I mean it.
Double-checked locking doesn't work
That brings us to double-checked locking, an idiom for Singleton creation many authors, including myself, have talked about. With double-checked locking, you avoid unnecessary overhead in creating a one-of-a-kind Singleton object (accessed by a static accessor method that creates the object the first time it's called and subsequently returns the object created in the initial call). The double-check idiom tries to reduce synchronization overhead by locking only when the object is created rather than in every call to the accessor method. Here's the idiom:
class Disfunctional_singleton
{ private static Disfunctional_singleton the_instance;
private Disfunctional_singleton()
{ // Bunches of reads and writes that initialize
// the object occur here.
}
public static Disfunctional_singleton get_instance()
{ if( the_instance == null )
synchronized( Disfunctional_singleton.class )
{ if( the_instance == null )
the_instance = new Disfunctional_singleton();
}
return the_instance;
}
}
Two tests are required because a thread might be preempted after the first test but before the synchronized statement executes. The interrupting thread would then create the object, and the initial (suspended) thread, when it's released, would create a second object.
That seems clever, but unfortunately the code does not work ! The problem: the assignments that occur within the constructor occur within the same memory barrier as the assignment to the_instance . As a consequence, it's possible for the_instance to be non-null, even though the assignments th
Read
Tutorial at: Click here to view the tutorial
Rate Tutorial: Warning! Threading in
a multiprocessor world - JavaWorld February 2001
View Tutorial: Warning! Threading in
a multiprocessor world - JavaWorld February 2001
Related
Tutorials:
|
Displaying 1 - 50 of about 640 Related Tutorials.
|
Definition of Bioinformatics
;
About Bioinformatics
In February 2001, the human genome was finally... the roles of certain genes with those of other species in the living
world (using... for Biotechnology Information (NCBI
2001) defines bioinformatics as:
" |
Beep
Java: Beep
Java NotesBeep
A beep sound can be use to indicate a warning or error.
However, it is often better to give a warning dialog
box with a description of the problem |
Hello World in Echo3 framework
Hello World in Echo3 framework
Hello World in Echo3 framework
 ...;window.setTitle("Hello World");
  |
Hello world pdf
hello world pdf
hello world pdf
 ...;document.add(new Paragraph("Hello World"));
  |
Objective C Hello World
Objective C Hello World
Objective C Hello World... Hello World program. In the next section I will show you how to compile and
execute the Objective C Hello World example on windows machine.
Create first |
Hello World JSP Page
Hello World JSP Page
Hello World JSP Page... illustrates you how to print
simple "Hello World!" string on the browser.... Following code of the
program prints the string "Hello World!" by using < |
Writing Hello World
Servlet Hello World,Helloworld Servlet Example,Java Servlet Hello World Example
Writing Servlet Hello World
  |
"Hello World" example in Wicket
;
Hello World example... added the
"Hello World!" message. Full code of HelloWorld.java...;Hello World!"));
}
}
This HelloWorld class output |
jQuery to "Hello World"
is the code of
PHP script (helloWorld.php).
<?
print $hello_world="Hello World";
?>
Step 2:
Write HTML page to call the helloWorld.php. |
Displaying Hello World using GWT
Displaying Hello World using GWT
Displaying Hello World using GWT
 ... for displaying Hello World
using GWT in java. By GWT we mean Google Web Toolkit |
Dojo Hello World
Dojo Hello World
Dojo Hello World... directory
structure.
Try Online: Hello
World
Create a Button
The following example we are going to create a button
"Hello World!". To create |
Hello world (First java program)
for Beginners in Java
Hello world (First java program... and can be run on any operating System. Writing Hello World
program is very
simple. To write the Hello world program you need simple text
editor like note pad |
Struts 2 Hello World Application Example, Learn how to develop Hello World application in struts 2.
Struts 2 Hello World,Struts Hello World,Developing Hello World
Application
Struts 2 Hello World - Developing
Hello World Application
  |
Developing JSP, Java and Configuration for Hello World Application
Writing JSP, Java and Configuration for Hello World Application,Struts 2
Hello World
Writing JSP, Java and Configuration for Hello World Application
  |
Programming - World Peace
Java: Exercise - Programming - World Peace
Java: Programming - World Peace
Change all occurences... to produce world peace
by scanning the input for the word "war" and replace |
Very simple `Hello world' java program that prints HelloWorld
Very simple `Hello world' java program that prints HelloWorld
Hello World Java
Simple Java... World program is stepwise step. This short
example shows how to write first |
Hello World Quartz Scheduler
Quartz Scheduler Tutorial, Hello World Quartz Scheduler
Hello World Quartz Scheduler
 ... framework. That will
display "Hello World Quartz Scheduler :<date & |
Java - Applet Hello World
Java Applet, Java Applet Hello World Examples
Java - Applet Hello World
 ... that displays Hello World message.
import java.applet.Applet |
Hello World Program in JRuby
Hello World Program in JRuby
Hello World Program...
require "java"
stringHello= "Hello World"
stringDate... HelloWorld.rb
Hello World
Date := Tue Sep 23 18:12:26 GMT+05:30 2008 |
JFreeChart - An Introduction
java chart library.
David Gilbert founded the JFreeChart project in February 2000 |
Simple Procedure to display Hello World
Simple Procedure to display Hello World
Simple Procedure to display Hello World
 ... Simple Procedure that helps you
to display 'Hello World'. In this Example, we |
Deploying Hello World Application on Apache Geronimo Application Server
Apache Geronimo Hello World Application Test, Deploying Hello World... Hello World Application on Apache Geronimo Application Server
 ... will develop Hello World JSP
application and test on the Apache Geronimo |
How to write hello world by using Multiple Writers in pdf
How to write hello world in pdf
How to write hello world by using
Multiple Writers in pdf
 ...(new Paragraph("Hello World"));
  |
'Hello World' file from a servlet (PDF, HTML or RTF).
Inserting image in the pdf file
'Hello World' file
from a servlet (PDF, HTML or RTF).
  |
Hello world (First java program)
Hello world
Hello world (First java program... be run on any operating System. Writing Hello World
program is very simple. To write the Hello world program you need simple
text editor like note pad |
Understanding Hello World Java Program
Hello World Program Java,Hello World First Program,Hello World Java,Online Hello World Java Program
Understanding Hello World...;Hello, World");
  |
Understanding Hello World Java Program
Hello World Program Java,Hello World First Program,Hello World Java,Online Hello World Java Program
Understanding Hello World...;Hello, World");
  |
"Hello World" program in Swing and JRuby
"Hello World" program in Swing and JRuby
"... .
frame.getContentPane().add(javax.swing.JLabel.new("Hello World")) will
add a new JLabel... World"))
frame.setDefaultCloseOperation(javax.swing.JFrame::EXIT_ON_CLOSE |
Beep Java
can create a beep sound to indicate a warning or error by using java.
However, it is often better to give a warning dialog box with a description |
Writing First Hello World application in JSP
Create your first hello world web page with jsp
Create your first hello world web page with jsp
 ...>
<body bgcolor="white">
<h1>
HELLO World
< |
Java error icon
, information, warning,
and error). Each icon have different look and feel and have |
Create a Custom Log Level in Java
, WARNING, SEVERE, FINEST etc. See
brief information about the topic and an example |
Rogue Dialers - The Nets Latest Scamola!
the world over are already being hit by a new breed of trojan type software called... containing HTML and embedded malevolent code, to be previewed without any warning |
Java Script Programming Books
Yourself Java Script
The World Wide Web began as a simple repository..., we'll discuss the W3C DOM, a standard document object model defined by the World... JavaScript Programs for the World Wide Web." A reference/guide to the wonders |
Open Source Outlook
are still locked into their propietary, vertically locked down world; we need....
The Mozilla Foundation revealed in February at the Free and Open Source |
Bayanihan Linux 4 Beta 1 has been released
and Technology Institute last October 2001. This was the first initiative... by February 2.
After three BETA version and a release candidate, the final version of Bayanihan Linux 3 was finally launched last February 24, 2004 during |
Hibernate Quickly
Hibernate Quickly,Hibernate Quick Start,Hibernate QuickStart,Hibernate Quick Reference,Hibernate Reference
Hibernate Quickly
In this fast changing programming world, each day new technologies are coming |
Building Suggestion Box Using GWT
;
Displaying Hello World using GWT
This example describes the process for displaying Hello World
using GWT |
Cookies in JSP
;
In world wide web the protocol we use is a http
protocol. The Http |
OOPs and Its Concepts in Java
to create programs based on the real world. Unlike
procedural programming, here |
Use of BasicConfigurator in Log4j logging
;
log4j warning
log4j... to
configure log4j using BasicConfigurator.
Now lets see when this log4j warning...;logger.debug("Hello world.");
  |
RR64 Linux 3.0 Beta 1 has been released
Linux is the world's most complete GNU/Linux distribution based on Gentoo unstable... Computers. So, jump into the world of RR4 and RR64 Linux without losing your love...).
Some more information about the RR64
Linux and Feature
RR64 Linux is the World's |
Iteration
of values to solve real-world
problems.
The for Statement
In the world of Java programming, the for loop has made
the life much more easier... we will print 'Hello World' ten
times using for loop |
How To Choose A Fire Wall Software Program
world a "fire wall" is a fireproof wall that is built to stop the spread of fire from one part of a building to others. In the Internet world a firewall has |
Introduction to Server Side Programming
programming in Java with the ever famous ?Hello World!? program. If you can recollect... significance when it comes to real world programming.
Why Server |
MySQL 5.0 Release - Download MySQL 5.0
MySQL 5.0 is the latest version of the world's most popular
open source database |
Java Training Delhi
;
Java Training in Delhi from Java Experts!
We offer world |
Pros and Cons of LBS
innovation in today’s world as it contributes a lot in bringing changes |
GPS in Health Improvement & Physical Training
of health is now one of the most concerned topics in all over the world |
Session In JSP
Protocol.
It is the protocol used to convey information of World Wide Web (WWW |
|
|
|