import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Main {
    public static void main(String[] args) {
        Brojac b = new Brojac();
        Brojac b2 = new Brojac();
        MyThread t1 = new MyThread(1, b);
        MyThread t2 = new MyThread(2, b2);
        t1.start();
        t2.start();
        try {
            t1.join();
            t2.join();
        }
        catch (InterruptedException ie) {
            System.out.println(ie);
        }
       System.out.println(b.getBr());
        System.out.println(b2.getBr());

    }
}

class MyThread extends Thread {
    private int id;

    Brojac b;
    public MyThread(int _id, Brojac _b) {
        id = _id;
        b = _b;
    }

    @Override
    public void run() {
        for(int i = 0; i < 10; ++i) {
//            System.out.println("Thread " + id + " " + i);
            b.zgolemi_brojac_semaphore();
            // zemi ja vrednosta na b
            // zgolemi ja vrednosta T1, T2
            // vrati ja vrednost
        }
    }
}

class Brojac {
    private static int br = 0;
    private static Lock lock = new ReentrantLock();
    private static Semaphore semaphore = new Semaphore(2);
    public static void unsafe_zgolemi_brojac() {
        br++; // no atomicity
        try {
            Thread.sleep(10);
        }
        catch (InterruptedException ie) {
            System.out.println(ie);
        }
    }
    public synchronized void safe_zgolemi_brojac() {
        br++; // atomocity
    }
    public void safe_zgolemuvanje() {
        synchronized (this) {
            br++;
        }
    }
    public static void zgolemi_brojac_mutex() {
        lock.lock();
        br++;
        lock.unlock();
    }
    public static void zgolemi_brojac_semaphore()  {
        try {
            semaphore.acquire();
            br++;
            semaphore.release();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static int getBr() {
        return br;
    }

}