Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swapping variables in a multi-threaded environment

Tags:

java

I was recently asked a question that stumped me.

public void swapEngine(Car a, Car b) {
  Engine temp = a.engine;
  a.engine = b.engine;
  b.engine = temp;
}

This is not a thread-safe method. If Thread 1 calls swapEngine(car1, car2) and then Thread 2 calls swapEngine(car1, car3), it is possible for car2 to end up with the engine of car3. The most obvious way to fix this problem is to synchronize the method.

Synchronizing the method introduces a potential inefficiency. What if Thread 1 calls swapEngine(car1, car2) and Thread 2 calls swapEngine(car3, car4)? In no way can these two threads interfere with each other. In this case the ideal situation would be for the two threads to swap the engines in parallel. Synchronizing the method precludes this from happening.

Is there another technique to swap these engines in a thread-safe manner while still taking advantage of parallelism?

Edit: Made method public.

like image 568
Jeremy G Avatar asked May 05 '15 14:05

Jeremy G


People also ask

Can two threads use the same variable?

When these two threads execute the run method, they create their own copy of the local count variable inside their own private stack. As these stacks are private two threads cannot share the same copy of the count variable.

How do you swap variables in Java?

Two variables can be swapped in one line in Java. This is done by using the given statement. x = x ^ y ^ (y = x); where x and y are the 2 variables.

What are the ways to increase throughput of a multi threaded Java program?

By running instances or programs concurrently we ensure high throughput and higher performance as we can utilize the untapped resources like operating system hardware etc. For example, if a system has several CPUs, then the application can utilize these CPUs effectively and increase the throughput.


1 Answers

As the comments say, you can lock the cars themselves. This, however could cause a deadlock if cars are not always locked in the same order.

So, if cars have a unique identifier, you can simply sort the cars, and then swap:

void swapEngine(Car a, Car b) {
    Comparator<Car> byId = Comparator.comparing(Car::id);
    Car[] cars = new Car[] {a, b};
    Arrays.sort(cars, byId);
    doSwap(cars[0]), cars[1];
}

private void doSwap(Car a, Car b) { 
    synchronized(a) {
        synchronized(b) {
            Engine temp = a.engine;
            a.engine = b.engine;
            b.engine = temp;
        }
    }
}

If the cars don't have any unique ID allowing to compare them, you can sort them by their identity hashCode (obtained using System.identityHashCode(car)). This hashCode, unless you have a huge memory, an enormous amount of cars, and bad luck, is unique. If you really fear such a situation, then Guava has an arbitrary ordering that you can use.

like image 114
JB Nizet Avatar answered Oct 12 '22 19:10

JB Nizet