Aakash
Aakash

Reputation: 17

Adding or deleting elements concurrently from a Hashmap and achieving synchronization

I am new to Java and concurrency stuff.

The purpose of the assignment was to learn concurrency. - So when answering this question please keep in mind that I am supposed to use only Hashmap (which is not synchronized by nature) and synchronize it myself. If you provide more knowledge its appreciated but not required.

I declared a hashmap like this:

private HashMap<String, Flight> flights = new  HashMap<>();

recordID is the key of the flight to be deleted.

Flight flightObj = flights.get(recordID);

synchronized(flightObj){
                    Flight deletedFlight = flights.remove(recordID);
                    editResponse = "Flight with flight ID " + deletedFlight.getFlightID() +" deleted successfully";
                    return editResponse;
                }

Now my doubt: Is it fine to synch on the basis of flightObj?


Doubt 2:

Flight newFlight = new Flight(FlightServerImpl.createFlightID());
flights.put(newFlight.getFlightID(),newFlight); 

If I create flightts by using above code and if more than 1 thread try execute this code will there be any data consistency issues ? Why or why not?

Thanks in advance.

Upvotes: 1

Views: 482

Answers (2)

KayV
KayV

Reputation: 13845

You can do the following

class MySynchronizedHashMap<E> implements Collection<E>, Serializable {
    private static final long serialVersionUID = 3053995032091335093L;

    final Collection<E> c;  // Backing Collection
    final Object mutex;     // Object on which to synchronize

    SynchronizedCollection(Collection<E> c) {
        this.c = Objects.requireNonNull(c);
        mutex = this;
    }

    public boolean add(E e) {
        synchronized (mutex) {return c.add(e);}
    }
    public boolean remove(Object o) {
        synchronized (mutex) {return c.remove(o);}
    }
}

MySynchronizedHashMap mshm = new MySynchronizedHashMap<>(new HashMap<String, Flight>());
mshm.add(new Flight());

Upvotes: 0

Alex Libov
Alex Libov

Reputation: 1491

To quickly answer you questions:

Both are not okay - you can't remove two different objects in parallel, and you can't add two different objects in parallel.

From java documentation:

If multiple threads access a hash map concurrently, and at least one of the threads modifies the map structurally, it must be synchronized externally. (A structural modification is any operation that adds or deletes one or more mappings; merely changing the value associated with a key that an instance already contains is not a structural modification.) This is typically accomplished by synchronizing on some object that naturally encapsulates the map. If no such object exists, the map should be "wrapped" using the Collections.synchronizedMap method. This is best done at creation time, to prevent accidental unsynchronized access to the map:

So, it's okay for many threads to use get concurrently and even put that replaces an object.

But if you remove or add a new object - you need to synchronize before calling any hashmap function.

In that case you can either do what's suggested in the documentation and use a global lock. But, it seems that since some limited concurrency is still allowed, you could get that concurrency it by using a read/write lock.

Upvotes: 1

Related Questions