-2

Ok so as I understand it, its best to create a final static Object that I use for synchronization.

However, I also read that if the object reference doesn't change, then it won't have concurrency issues.

Do the following code violate synchronicity?

class Foo {
    private static ArrayList<Client> clients = null;

    public Foo() {
        clients = new ArrayList<>();
        //add stuff to list here..
    }

    public void addClient(Client C) {
        synchronized(clients) {
            clients.add(C);
        }
    }
}

Do I have to make clients final or create a final object if the clients ArrayList is never exposed directly (only other than through Getters)? In other words, I never provide a set method for the clients array so the reference never changes.

hoaz
  • 9,883
  • 4
  • 42
  • 53
Brandon
  • 22,723
  • 11
  • 93
  • 186

3 Answers3

3

Anyone creating an instance of Foo new Foo() overrides the clients array. it definitely is not thread safe

Asaf
  • 6,384
  • 1
  • 23
  • 44
  • How :S It's a static array.. – Brandon May 09 '13 at 19:02
  • being static does not mean it can not be assigned. what you want is for it to be final. but if you make it static final than the above code will not compile, because you can not make 2 assignments to the same member ( first null than an actual array ) – Asaf May 09 '13 at 19:04
2

If you really want clients to be static, i.e., there is one list of Clients shared by all Foos so that it collects a huge list of all Clients, then you need to initialize it only once.

private static ArrayList<Client> clients = new ArrayList();

But I suspect that you want one client list per Foo, in that case, don't declare it static and, for clarity, do declare it final. (There are also some weird corner cases where you really must declare it final, as described in Java Concurrency in Practice.)

user949300
  • 15,364
  • 7
  • 35
  • 66
  • Yes :) I wanted one list for all Foos so I made it static. I initialized it like yours and made it final. I wasn't sure because in C++, I can only initialize in constructor or initialization list. Still learning java. That's a neat feature. Thanks! – Brandon May 09 '13 at 19:13
1

To make it thread safe change the declaration of 'clients' like this:

private final static List<Client> clients = new ArrayList<Client>();

and use 'synchronized' as you already do.

In case you are confused of what the static keyword means: The static keyword means that the same instance of the 'clients' will be shared for all instances of Foo. If you remove the static keyword, each Foo instance will have it's own instance of 'clients'.

The final keyword simply prevents you from reassigning the clients variable.

Vegard
  • 4,352
  • 1
  • 27
  • 25