On Mon, Oct 12, 2009 at 7:18 PM, Nathan Beyer <[email protected]> wrote:
> Honestly, the synchronization probably isn't appropriate on any of the
> accessor/mutators - the granularity isn't correct. The locking
> probably needs to encompass the entire method on DatagramSocket while
> working on a particular DatagramPacket. Realistically, you don't want
> the packet to change while processing.
>
A test shows that the RI uses synchronized. The following program doesn't
complete:
public static void main(String[] args) throws Exception {
byte[] data = new byte[] { 1, 2, 3, 4, 5 };
final DatagramPacket datagramPacket = new DatagramPacket(data,
data.length);
ExecutorService executorService = Executors.newFixedThreadPool(1);
synchronized (datagramPacket) {
Future<byte[]> future = executorService.submit(new Callable<byte[]>()
{
public byte[] call() throws Exception {
return datagramPacket.getData();
}
});
byte[] fromAnotherThread = future.get();
System.out.println(Arrays.toString(fromAnotherThread));
}
}
Unfortunately, the concurrency support is shallow and not useful. Despite
the fact that the RI has synchronized statements, it fails to defensively
copy the data array:
public static void main(String[] args) throws Exception {
byte[] data = new byte[] { 1, 2, 3, 4, 5 };
final DatagramPacket datagramPacket = new DatagramPacket(data,
data.length);
System.out.println("arrays are defensively copied? " + (data !=
datagramPacket.getData()));
}
As a consequence, one thread could mutate the data array while another
thread is consuming it.
Regardless, it looks like synchronized and no defensive copying is the key
to compatibility with the RI.