import java.awt.geom.AffineTransform;
import java.util.concurrent.Semaphore;
import java.util.*;
public class Main {
    public static void main(String args[]) {
        init();
        List<Thread> si_atoms = new ArrayList<>();
        List<Thread> o_atoms = new ArrayList<>();
        for(int i = 0; i < 5; i++) {
            si_atoms.add(new Si());
        }
        for(int i = 0; i < 10; i++) {
            o_atoms.add(new O());
        }
        for(int i = 0; i < 5; i++) {
            si_atoms.get(i).start();
        }
        for(int i = 0; i < 10; i++) {
            o_atoms.get(i).start();
        }
        try {
            for (int i = 0; i < 5; i++) {
                si_atoms.get(i).join();
            }
            for (int i = 0; i < 10; i++) {
                o_atoms.get(i).join();
            }
        }
        catch (InterruptedException e) {
            System.out.println(e);
        }
    }
    static Semaphore si;
    static Semaphore o;
    static Semaphore si_created;
    static Semaphore o_created;
    static Semaphore boss;
    private static void init() {
        si = new Semaphore(1);
        o = new Semaphore(2);
        si_created = new Semaphore(0);
        o_created = new Semaphore(0);
        boss = new Semaphore(0);
    }
    static class Si extends Thread {
        public void bond() {
            System.out.println("Si is bonding");
        }
        private void go() throws InterruptedException {
            si.acquire();
            si_created.release(2);
            o_created.acquire(2);
            boss.release(2);
            bond();
            si.release();
        }
        @Override
        public void run() {
            try {
                go();
            }
            catch (InterruptedException e) {
                System.out.println(e);
            }
        }

    }
    static class O extends Thread {
        public void bond() {
            System.out.println("O is bonding");
        }
        private void go() throws InterruptedException {
            o.acquire();
            si_created.acquire(1);
            o_created.release(1);
            boss.acquire(1);
            bond();
            o.release();
        }
        @Override
        public void run() {
            try {
                go();
            }
            catch (InterruptedException e) {
                System.out.println(e);
            }
        }
    }
}
