Results 1 to 3 of 3
  1. #1
    OcketN is offline Member
    Join Date
    Apr 2010
    Posts
    3
    Rep Power
    0

    Default Sharing an array while synchronized

    Hi all,

    the following code is plain stupid and only had educational purposes, as i am busy studying concurrency.

    I will explain the problem first.

    I wanted to see what happened to a shared array when multiple 'tasks' access it and modify it. I expected to see trouble when i did not use synchronization. I didn't expect trouble while using synchronisation, but I have.

    I have this one class that contains the array. Its initial values are all 0. Then i have a method in that same class to modify the entire array. I add the same amount to every element of the array. This method is synchronized.

    Then i came up with a task (runnable) that executes the incrementation method. In a pool i create multiple of these tasks. The tasks check if all of the elements in the array are still the same. if not, the entire operation gets canceled.

    I would expect, when using synchronized for the entire method, that access to the array would be limited to one runnable at the time. Instead, after a few seconds, the application stops (because the threads have collided). But what is even more weird is that when i print the arrays from the runnables, the arrays are still 'correct'. The elements are all the same. Even more, the result of every thread is the same array.

    Can somebody explain to me what happens? Could it perhaps be hardware related?


    Here is the code:

    the main thread:

    Java Code:
    public class Main {
    
        public void volatileArray(){
    
            IntegerRegister register = new IntegerRegister();
            ExecutorService exec = Executors.newCachedThreadPool();
    
            for(int i = 0; i<4; i++){
                exec.execute(new IncrementArray(register, i));
            }
    
            exec.shutdown();
        }
    public static void main(String[] args) {
    
           Main main = new Main();
    
           main.volatileArray();
    
        }
    the class with the 'shared array':

    Java Code:
    public class IntegerRegister {
    
        private int[] register = new int[]{0,0,0,0,0,0};
    
        private boolean isCorrect = true;
    
        public synchronized int[] incrementRegister(int amount){
            for(int i=0; i<6; i++){
                register[i] = register[i]+amount;
            }
    
            return register;
        }
    
        public void cancelAllOperations(){
            isCorrect = false;
        }
    
        public boolean goodToGo(){
            return isCorrect;
        }
    }

    The runnable:

    Java Code:
    public class IncrementArray implements Runnable{
    
        private IntegerRegister intreg;
        private int taskNumber;
    
        private int[] register;
    
        public IncrementArray (IntegerRegister intreg, int taskNumber){
            this.intreg = intreg;
    
            this.taskNumber = taskNumber;
        }
    
        public void run() {
            while(intreg.goodToGo()){
    
                
                register = intreg.incrementRegister(taskNumber+1);
    
                int oldval = register[0];
                for(int i=1; i<register.length; i++){
                    if(oldval != register[i]){
                        intreg.cancelAllOperations();
                    }
                    else{
                        oldval = register[i];
                    }
                }
    
                System.out.println("\n");
            }
    
            System.out.println("Task "+taskNumber+" has terminated because register is messed up");
            if(register != null){
                 for(int i = 0; i< register.length; i++){
                    System.out.print(register[i]+" :");
                 }
            }
            else
                System.out.println("register is null");
        }
    
    }
    As you can see, i start up 4 of threads. It does take a while until i get a result, but in the end i get this:

    Task 0 has terminated because register is messed up
    257785 :257785 :257785 :257785 :257785 :257785 :

    Task 3 has terminated because register is messed up
    257785 :257785 :257785 :257785 :257785 :257785 :

    Task 1 has terminated because register is messed up
    257785 :257785 :257785 :257785 :257785 :257785 :

    Task 2 has terminated because register is messed up
    257785 :257785 :257785 :257785 :257785 :257785 :BUILD SUCCESSFUL (total time: 13 seconds)

  2. #2
    iluxa is offline Senior Member
    Join Date
    Mar 2010
    Posts
    266
    Rep Power
    5

    Default

    Things work as expected.

    The only thing your synchronization guarantees is that incrementRegister() is not called by two threads at the same time. So suppose one thread does

    register = incrementRegister();
    // start looking at register
    // ...
    // done looking at register

    nothing stops another thread from calling incrementRegister() during the //... step, thus changing the values of the array.

    if you want this block to be executed by only one thread at a time:

    // start looking at register
    // ...
    // done looking at register

    you have to synchronize it somehow.


    what exactly are you trying to accomplish?

  3. #3
    OcketN is offline Member
    Join Date
    Apr 2010
    Posts
    3
    Rep Power
    0

    Default

    Hello Iluxa,

    thank you for your reply!

    What i was trying to do was just studying actually. I wanted to see what would happen with an array with and without synchronisation and also that the volatile keyword does not protect against threads that manipulate elements of an array.

    But i think i get my mistake now. Although the place where the array gets incremented is thread safe, the place where i read the array (in the callables) is not that safe. While one task has finished and reads to array to check if it is still correct, another task might already have changed it right in the middle of the first task iterating over that array. And this happens because every task references to the same array.

    I went over the code multiple times, and know that you showed me my mistake, i keep on wondering how come i didnt figure it out myself :)

    Thanks Iluxa

Similar Threads

  1. Synchronized(this)?
    By kiza in forum Threads and Synchronization
    Replies: 10
    Last Post: 04-07-2009, 02:20 PM
  2. Synchronized Servlet
    By udayadas in forum Java Servlet
    Replies: 5
    Last Post: 09-09-2008, 09:14 PM
  3. synchronized
    By bugger in forum New To Java
    Replies: 2
    Last Post: 11-28-2007, 11:33 AM
  4. doubt about synchronized
    By simon in forum Advanced Java
    Replies: 2
    Last Post: 08-05-2007, 04:49 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •