0

As per my understanding Vector should block the whole collection for additional threads if one thread is already accessing it. I am trying to

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.concurrent.CopyOnWriteArrayList;

public class MyTest1{
    
//  static ArrayList<String> l1 = new ArrayList<>(Arrays.asList("A", "B", "C"));
    static Vector<String> l1 = new Vector<>(Arrays.asList("A", "B", "C"));
//  static List<String> l1 = Collections.synchronizedList(Arrays.asList("A", "B", "C"));

    public static void main(String[] args) {
        Thread t1 = new Thread(new MyThread1());
        Thread t2 = new Thread(new MyThread2());
        t1.start();
        t2.start();
        System.out.println(Thread.currentThread() + "adding X " + l1.add("X"));
        System.out.println(Thread.currentThread() + "adding Y " + l1.add("Y"));
        System.out.println(Thread.currentThread() + "adding Z " + l1.add("Z"));
        
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(l1);
    }
    
    static class MyThread1 implements Runnable{
        @Override
        public void run() {
            System.out.println(Thread.currentThread() + "adding D " + l1.add("D"));
            System.out.println(Thread.currentThread() + "adding E " + l1.add("E"));
            System.out.println(Thread.currentThread() + "adding F " + l1.add("F"));
        }
    }
    static class MyThread2 implements Runnable{
        @Override
        public void run() {
            System.out.println(Thread.currentThread() + "removing A " + l1.remove("A"));
            System.out.println(Thread.currentThread() + "removing B " + l1.remove("B"));
            System.out.println(Thread.currentThread() + "removing C " + l1.remove("C"));
        }
    }
    
}

output:

Thread[main,5,main]adding X true
Thread[Thread-1,5,main]removing A true
Thread[Thread-1,5,main]removing B true
Thread[Thread-0,5,main]adding D true
Thread[Thread-1,5,main]removing C true
Thread[main,5,main]adding Y true
Thread[Thread-0,5,main]adding E true
Thread[main,5,main]adding Z true
Thread[Thread-0,5,main]adding F true
[X, D, Y, E, Z, F]

The output should not be like this. It should be 3 consecutive add or remove for a specific thread. What I am missing here? Please help.

Holger
  • 285,553
  • 42
  • 434
  • 765
Shashank
  • 712
  • 15
  • 33

1 Answers1

6
  1. Vector guarantees atomicity of a single operation
  2. Vector does not guarantee atomicity of a sequence of operations

In the code in question,

  1. add and remove operations are synchronized individually(independently) - at any given time, only one of this operation can be performed on the object
  2. it does not synchronize across different invocations of these operations over time

If you need synchronization across a set of operations,

  1. explicitly synchronize on the collection
  2. In the current case, then ArrayList should be fine when used with synchronization
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

class MyTest1 {

    static List<String> l1 = new ArrayList<>(Arrays.asList("A", "B", "C"));

    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            synchronized (l1) {
                System.out.println(Thread.currentThread() + "removing A " + l1.remove("A"));
                System.out.println(Thread.currentThread() + "removing B " + l1.remove("B"));
                System.out.println(Thread.currentThread() + "removing C " + l1.remove("C"));
            }
        });
        Thread t2 = new Thread(() -> {
            synchronized (l1) {
                System.out.println(Thread.currentThread() + "removing A " + l1.remove("A"));
                System.out.println(Thread.currentThread() + "removing B " + l1.remove("B"));
                System.out.println(Thread.currentThread() + "removing C " + l1.remove("C")); 
            }
        });
        t1.start();
        t2.start();
        synchronized (l1) {
            System.out.println(Thread.currentThread() + "adding X " + l1.add("X"));
            System.out.println(Thread.currentThread() + "adding Y " + l1.add("Y"));
            System.out.println(Thread.currentThread() + "adding Z " + l1.add("Z"));
        }

        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(l1);
    }
}
Thiyanesh
  • 2,360
  • 1
  • 4
  • 11