Home > Blockchain >  Java 2 Threads exclusion concurrently work on different methods
Java 2 Threads exclusion concurrently work on different methods

Time:12-01

I have to use Semaphore to work on two different processes at the same time. But they work in a specific sequence and have to exclude each other.

Process 1 "p1" has to print out first number "1" and after p1 is ready, p2 is allowed to work and print out the number 2. After p2 has finished, p1 should be allowed to work again on p1 and after p2 and so on.. The output shoult be 12121212....121212. My solution has somewhere an error and I am not able to see where it is. Unfortunately I need to solve this problem with a Semaphore. I think the problem could also be solved with mutex.

How would the solution look like for: Semaphore? Mutex?

I initialized two Semaphores sem1 and sem2. Sem1 has a permit of 1 and sem2 starts with a permit of 0.

Both threads start simultaneously but since sem2 doesn't have a permit, sem1 enters the critical area with the acquire(); method. There it prints out "1" and after it's done, it will release a permit for sem2.

sem2 is now allowed to enter its process with acquire(); and prints out "2", when it is finished it releases a permit for sem1.

The algorithm should continue this way, but somewhere is a lock and the program stops after printing 1

import java.util.concurrent.Semaphore;

public class SemTest {
    Semaphore sem1 = new Semaphore(1);
    Semaphore sem2 = new Semaphore(0);

    public static void main(String args[])
    {

        final SemTest semTest1 = new SemTest();
        final SemTest semTest2 = new SemTest();

        new Thread()
        {
            @Override
            public void run()
            {
                try {
                    semTest1.numb1();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }.start();
        
        new Thread()
        {
            @Override
            public void run()
            {
                try {
                    semTest2.numb2();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }.start();
    }

    private void numb1()
    {
        while (true) {
            try {
                sem1.acquire();
                System.out.println(" 1");
                sem2.release();

                Thread.sleep(1000);
            }
            catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
    private void numb2()
    {
        while (true) {
            try {
                sem2.acquire();
                System.out.println(" 2");
                sem1.release();
                Thread.sleep(1000);
            }

            catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

CodePudding user response:

I am not sure this is the right way to fix things, but I moved some code around and removed confusion around the sem1 and sem2 variable names.

package semaphore;

import java.util.concurrent.Semaphore;

public class MySemaphore {

    public static void main(String args[]) {

        Semaphore sem1 = new Semaphore(1);
        Semaphore sem2 = new Semaphore(0);

        new Thread()
        {
            @Override
            public void run()
            {
                try {
                    numb1();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }

            private void numb1()
            {
                while (true) {
                    try {
                        sem1.acquire();
                        System.out.println(" 1");
                        sem2.release();

                        Thread.sleep(1000);
                    }
                    catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

            }
        }.start();

        new Thread()
        {
            @Override
            public void run()
            {
                try {
                    numb2();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }

            private void numb2()
            {
                while (true) {
                    try {
                        sem2.acquire();
                        System.out.println(" 2");
                        sem1.release();
                        Thread.sleep(1000);
                    }

                    catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }
}

The correct output seems to be given:

 1
 2
 1
 2
 1
 2
 1
 2
...

CodePudding user response:

The problem is, your program creates two instances of the SemTest (as I renamed it) class. Each instance has its own distinct sem1 and sem2 fields. Each of your two threads operates on a different instance of the class with its own semaphores, so they do not interact with each other at all.

@hooknc showed you one way to fix it. In that answer, the sem1 and sem2 semaphores are moved into the main() method, and they are captured by your two anonymous Runnable objects. Since both Runnables captured the same two Semaphores, the two threads are now able to interact with each other.

  • Related