0

I wanted to implement a traffic signal (a single box). I saw there were many questions in SO, but I felt they were not complete code.

The below is the full source. I am using lock and condition for deciding which thread will actually run.

TrafficSignalSimulationUsingLock.java

package com.example.practice.third;

import java.util.concurrent.locks.Condition;

import com.example.practice.third.custom.lock.TrafficLock;
import com.example.practice.third.threads.GreenColorLightThread;
import com.example.practice.third.threads.RedColorLightThread;
import com.example.practice.third.threads.YellowColorLightThread;

public class TrafficSignalSimulationUsingLock {

    public static void main(String[] args) throws InterruptedException {

        TrafficLock lock = new TrafficLock();

        Condition condition = lock.newCondition();

        Thread redThread = new Thread(new RedColorLightThread(lock, condition));
        Thread yellowThread = new Thread(new YellowColorLightThread(lock, condition));
        Thread greenThread = new Thread(new GreenColorLightThread(lock, condition));

        redThread.start();

        Thread.sleep(300);

        yellowThread.start();
        greenThread.start();

        redThread.join();
        yellowThread.join();
        greenThread.join();
    }
}

RedColorLightThread.java

package com.example.practice.third.threads;

import java.util.concurrent.locks.Condition;

import com.example.practice.third.custom.lock.TrafficLock;

public class RedColorLightThread implements Runnable {

    private TrafficLock trafficLock;
    private Condition condition;

    public RedColorLightThread(TrafficLock trafficLock, Condition condition) {
        this.trafficLock = trafficLock;
        this.condition = condition;
    }

    @Override
    public void run() {

        while (true) {
            try {
                trafficLock.lock();

                while (trafficLock.isYellow() && trafficLock.isGreen()) {
                    try {
                        condition.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                for (int i = 0; i < 5; i++) {
                    System.out.println("Red signal enabled");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                trafficLock.setYellow(true);
                trafficLock.setGreen(false);
                condition.signalAll();

            } finally {
                trafficLock.unlock();
            }
        }
    }
}

YellowColorLightThread.java

package com.example.practice.third.threads;

import java.util.concurrent.locks.Condition;

import com.example.practice.third.custom.lock.TrafficLock;

public class YellowColorLightThread implements Runnable {

    private TrafficLock trafficLock;
    private Condition condition;

    public YellowColorLightThread(TrafficLock trafficLock, Condition condition) {
        this.trafficLock = trafficLock;
        this.condition = condition;
    }

    @Override
    public void run() {

        while (true) {
            try {
                trafficLock.lock();

                while (trafficLock.isRed() && trafficLock.isGreen()) {
                    try {
                        condition.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                for (int i = 0; i < 3; i++) {
                    System.out.println("Yellow signal enabled");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                trafficLock.setRed(false);
                trafficLock.setGreen(true);
                condition.signalAll();

            } finally {
                trafficLock.unlock();
            }
        }
    }
}

GreenColorLightThread.java

package com.example.practice.third.threads;

import java.util.concurrent.locks.Condition;

import com.example.practice.third.custom.lock.TrafficLock;

public class GreenColorLightThread implements Runnable {

    private TrafficLock trafficLock;
    private Condition condition;

    public GreenColorLightThread(TrafficLock trafficLock, Condition condition) {
        this.trafficLock = trafficLock;
        this.condition = condition;
    }

    @Override
    public void run() {

        while (true) {
            try {
                trafficLock.lock();

                while (trafficLock.isRed() && trafficLock.isYellow()) {
                    try {
                        condition.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                for (int i = 0; i < 5; i++) {
                    System.out.println("Green signal enabled");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                trafficLock.setRed(true);
                trafficLock.setYellow(false);
                condition.signalAll();

            } finally {
                trafficLock.unlock();
            }
        }
    }
}

TrafficLock.java

package com.example.practice.third.custom.lock;

import java.util.concurrent.locks.ReentrantLock;

public class TrafficLock extends ReentrantLock {

    /**
     * 
     */
    private static final long serialVersionUID = 7311233763066170670L;

    private boolean red = true;
    private boolean yellow = false;
    private boolean green = false;

    public TrafficLock() {
        super(true);
    }

    public boolean isRed() {
        return red;
    }

    public void setRed(boolean red) {
        this.red = red;
    }

    public boolean isYellow() {
        return yellow;
    }

    public void setYellow(boolean yellow) {
        this.yellow = yellow;
    }

    public boolean isGreen() {
        return green;
    }

    public void setGreen(boolean green) {
        this.green = green;
    }
}

The below is sample output:

Red signal enabled
Red signal enabled
Red signal enabled
Red signal enabled
Red signal enabled
Yellow signal enabled
Yellow signal enabled
Yellow signal enabled
Green signal enabled
Green signal enabled
Green signal enabled
Green signal enabled
Green signal enabled
Red signal enabled
Red signal enabled

Is this correct way of implementing (pls ignore space , time complexities).

Although this program gives result what I expect, I have a small doubt:

In each "color thread" (e.g. "RedColorLightThread"), the thread first sets the next desired state, followed by condition.signalAll() and in finally block releases the lock.

My doubt is, won't other threads get awake instantaneously when for example "red color thread" hasn't still released the lock?

CuriousMind
  • 8,301
  • 22
  • 65
  • 134

1 Answers1

0

The locks can only be held by one thread at a time. When you signal the other threads, you are telling them that they can wake and try to get the lock, but they will only move on when they get the lock. That only happens when the the other thread unlocks it. After that only of the waiting threads will wake and lock the lock, while the others keep waiting.