...
Code Block |
---|
|
class RaceCollection {
private List<InetAddress> ips = Collections.synchronizedList(new ArrayList<InetAddress>());
public void addIPAddress(InetAddress ia) {
// Validate
ips.add(ia);
}
public void doSomethingaddAndPrintIP() throws UnknownHostException {
addIPAddress(InetAddress.getLocalHost());
InetAddress[] ia = (InetAddress[]) ips.toArray(new InetAddress[0]);
System.out.println("Number of IPs: " + ia.length);
}
}
|
When the doSomethingaddAndPrintIP()
method is invoked on the same object from multiple threads, the output, consisting of varying array lengths, indicates a race condition between the threads. In other words, the statements that are responsible for adding an IP address and printing it out are not sequentially consistent. Also note that the operations within a thread's run()
method are non-atomic.
...
This noncompliant code example extends the base class and synchronizes on the doSomethingaddAndPrintIP()
method which is required to be atomic.
Code Block |
---|
|
class RaceCollectionSub extends RaceCollection {
public synchronized void doSomethingaddAndPrintIP() throws UnknownHostException {
addIPAddress(InetAddress.getLocalHost());
InetAddress[] ia = (InetAddress[]) ips.toArray(new InetAddress[0]);
System.out.println("Number of IPs: " + ia.length);
}
}
|
...
This noncompliant code example appears to use synchronization when defining the doSomethingaddAndPrintIP()
method, however, it acquires an intrinsic lock instead of the lock of the List
object. This means that another thread may modify the value of the List
instance when the doSomethingaddAndPrintIP()
method is executing.
Code Block |
---|
|
class Helper {
public List<InetAddress> ips = Collections.synchronizedList(new ArrayList<InetAddress>());
public synchronized void addIPAddress(InetAddress ia) {
// Validate
ips.add(ia);
}
public synchronized void doSomethingaddAndPrintIP() throws UnknownHostException {
addIPAddress(InetAddress.getLocalHost());
InetAddress[] ia = (InetAddress[]) ips.toArray(new InetAddress[0]);
System.out.println("Number of IPs: " + ia.length);
}
}
|
...
Code Block |
---|
|
public void addIPAddress(InetAddress ia) {
synchronized(ips) { // Also synchronize this method
// Validate
ips.add(ia);
}
}
public void doSomethingaddAndPrintIP() throws UnknownHostException {
synchronized(ips) {
addIPAddress(InetAddress.getLocalHost());
ia = (InetAddress[]) ips.toArray(new InetAddress[0]);
System.out.println("Number of IPs: " + ia.length);
}
}
|
...
Code Block |
---|
|
class CompositeCollection {
private List<InetAddress> ips;
public CompositeCollection(List<InetAddress> list) {
this.ips = list;
}
public synchronized void addIPAddress(InetAddress ia) {
// Validate
ips.add(ia);
}
public synchronized void doSomethingaddAndPrintIP() throws UnknownHostException {
addIPAddress(InetAddress.getLocalHost());
InetAddress[] ia = (InetAddress[]) ips.toArray(new InetAddress[0]);
System.out.println("Number of IPs: " + ia.length);
}
}
|
...