On Mon, Oct 12, 2009 at 7:18 PM, Nathan Beyer <nbe...@gmail.com> 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.

Reply via email to