0

How to make the following Java class thread safe?

class Test { int size; int index; String[] a; Test() { a = new String[10]; size = 10; } Test(int b) { a = new String[b]; size = b; } public int getSize() { return size; } public void addElement(String s) { if (a.length < size) { a[index] = s; index++; } else { // ... } } public String getElement(int i) { if (i < index) { return a[i - 1]; } else { return 0; } } } 
  1. Is it enough to make the String[] a; variable volatile?
  2. Or do i need to use the synchronized keyword?

My assumption is that synchronized is not needed for the methods getSize() and getElement(). Is that correct?

3
  • the best way to create thread save objects is to define them immutable!! Commented Jul 3, 2020 at 6:44
  • All instance variables must be private. Commented Jul 3, 2020 at 6:55
  • 1
    1. No. 2. Yes.: You have two options: Either you synchronize the access on the fields correctly or you make Test an immutable class. I'm sure someone will post an answer soon with more details. Commented Jul 3, 2020 at 6:58

1 Answer 1

2

To answer your questions:

  1. Volatile is a mechanisms for data integrity. Basically you are telling the compiler that a variable is likely to change by code executing in another thread, so that it should always get it from memory and not from the cache.

  2. synchronized is the way to go in you case. For a synchronized array what you need to protect are the writes because they will modify the contents of the array. Additionally, as pointed out in the comments, adding the synchronized keyword to the getElement method will guarantee that it will get executed after any concurrent addElement call so it will always use the most recent elements in the array. The official docs on Synchronized Methods has more details.

     class Test { private final int size; private final String[] a; private int index; Test() { this(10); } Test(int b) { this.a = new String[b]; this.size = b; this.index = 0; } public int getSize() { return size; } public synchronized void addElement(String s) { if (a.length < size) { a[index] = s; index++; } else { throw IndexOutOfBoundsException("Can't hold more elements"); } } public synchronized String getElement(int i) { if (i < index) { return a[i - 1]; } else { return 0; } } } 
Sign up to request clarification or add additional context in comments.

6 Comments

+ make the fields (size, index, a) private to make shure they can only be changed in synchronized context.
@VinZ added complete code example with your suggestions
index cannot be final.
Also, getElement has to be synchronized for thread safety. this.index = 0; is useless.
if you don't initialise the index then you would get a null pointer exception when you call a[index]. Two threads can safely call getElement so no need for synchronisation since getElement does not modify the state of the Test instance.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.