1

Suppose I have 10 threads that are incrementing a variable by 1. Suppose Thread-1 increments a variable first, and then Thread-2 and Thread-3 and consecutively. after all the 10 Threads have incremented the variable. I need to decrement the same variable in a manner.

Decrementing, if Thread-1 incremented the variable first of all, then it should decrement at last.

We need to do this without setting thread priority.

3
  • 1
    Consecutively not something you want use Multi threading for. Commented Jul 11, 2018 at 11:21
  • i know but i want to do it with multi-threading only.let's just say i have a requirement. Commented Jul 11, 2018 at 11:22
  • You can add some kind of shared logic which determine the order, ie a Class with an AtomicInteger, starting with value 1. All threads checking the value constantly where only the thread that equals that number (assign a number 1 to 10 to these threads) executes part 1 (increment). Then the AtomicInteger is incremented by one etc... When it reaches 10 the 10th thread executing part 2 (decrement) etc... Commented Jul 11, 2018 at 11:37

2 Answers 2

2

you can use a lot of ways, here's one for example:

public class Main {
    public static void main(String[] args) throws Exception {
        for(int i=0;i<10;i++){
            final int _i=i;
            Thread t = new Thread(new T(_i));
            t.start();
      }
    }
    public static class T implements Runnable{
        int threadNumber;
        public T(int threadNumber) {
            this.threadNumber=threadNumber;
        }

        @Override
        public void run() {
            increase(this);
        }
    }
    static Thread[] threads = new Thread[10];
    static int number  =0;
    static Object generalLock=new Object();
    public static void increase(T t){
        int myNumber=0;
        synchronized (generalLock){
            myNumber=number;
            System.out.println("i am "+number+" incrementing, my real number "+t.threadNumber);
            threads[number]=Thread.currentThread();
            number++;
        }
        while (threads[9]==null){
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        for(int i=9;i>myNumber;i--){
            try {
                threads[i].join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        synchronized (generalLock){
            System.out.println("i am "+number+" decrementing, my real number "+t.threadNumber);
            number--;
        }
    }
}

output example:

i am 0 incrementing, my real number 1
i am 1 incrementing, my real number 8
i am 2 incrementing, my real number 9
i am 3 incrementing, my real number 7
i am 4 incrementing, my real number 6
i am 5 incrementing, my real number 5
i am 6 incrementing, my real number 0
i am 7 incrementing, my real number 4
i am 8 incrementing, my real number 3
i am 9 incrementing, my real number 2
i am 9 decrementing, my real number 2
i am 8 decrementing, my real number 3
i am 7 decrementing, my real number 4
i am 6 decrementing, my real number 0
i am 5 decrementing, my real number 5
i am 4 decrementing, my real number 6
i am 3 decrementing, my real number 7
i am 2 decrementing, my real number 9
i am 1 decrementing, my real number 8
i am 0 decrementing, my real number 1

Note: you can use simple Runnable, I create T class to show the thread number in order to print it while incrementing/decrementing

Sign up to request clarification or add additional context in comments.

Comments

1

This seems to work. Essentially I create the 10 threads and specially identify one of them using an enum. They all try to increment the shared integer, identifying themselves. The incrementer detects the first increment by noticing the transition to 1 and if it's a Special thread it returns true .

There's also a CountDownLatch used to synchronise all of the threads to ensure there is at least a chance of the two alternatives. I get about 8600 out of the 10000 test runs where the Special got there first. This value will vary depending on many variables.

enum Who {
    Special, Normal;
}

class PriorityIncrementer {
    final AtomicInteger i = new AtomicInteger(0);

    boolean inc(Who who) {
        return i.incrementAndGet() == 1 && who == Who.Special;
    }

    public void dec() {
        i.decrementAndGet();
    }
}

class TestRunnable implements Runnable {
    final Who me;
    final PriorityIncrementer incrementer;
    final CountDownLatch latch;

    public TestRunnable(PriorityIncrementer incrementer, CountDownLatch latch, Who me) {
        this.incrementer = incrementer;
        this.latch = latch;
        this.me = me;
    }

    @Override
    public void run() {
        // Wait for all others to get here.
        latch.countDown();
        try {
            // Wait here until everyone os waiting here.
            latch.await();
            // Do it.
            if(incrementer.inc(me)) {
                // I was first and special, decrement after.
                incrementer.dec();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

private boolean test(int count) throws InterruptedException {
    Thread[] threads = new Thread[count];
    // The shared incrementer.
    PriorityIncrementer incrementer = new PriorityIncrementer();
    // Arrange for all of them to synchronise.
    CountDownLatch latch = new CountDownLatch(threads.length+1);
    // One special.
    threads[0] = new Thread(new TestRunnable(incrementer, latch, Who.Special));
    // The rest are normal.
    for(int i = 1; i < threads.length; i++) {
        threads[i] = new Thread(new TestRunnable(incrementer, latch, Who.Normal));
    }
    // Start them up.
    for (Thread thread : threads) {
        thread.start();
    }
    // Wait a moment.
    Thread.sleep(1);
    // Start them all going.
    latch.countDown();
    // Wait for them to finish.
    for (Thread thread : threads) {
        thread.join();
    }
    // Who won?
    return incrementer.i.get() < count;
}

public void test() throws InterruptedException {
    final int tests = 10000;
    int specialWasFirstCount = 0;
    for (int i = 0; i < tests; i++) {
        if(test(10)) {
            specialWasFirstCount += 1;
        }
    }
    System.out.println("Specials: "+specialWasFirstCount+"/"+tests);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.