KDP/Lab 1 RTI 2023

Izvor: SI Wiki
Pređi na navigaciju Pređi na pretragu

Ulazni test (WIP)

1. zadatak

Da li će doći do greške pri pozivu obj.a() u sledećem kodu?

public class A {
	public synchronized void a() {
		//neki kod ...
		b();
	}

	public void b() {
		//neki kod..
		notifyAll();
	}

	static A obj = new A();
}
  1. Da.
  2. Ne.

2. zadatak

Koji od sledećeg su validni načini da se inicijalizuje nit?

  1. Runnable r = new Runnable() {
    	    public void run(){ /*neki kod*/ }
    	};
    
  2. Runnable r = new Runnable() {
    		public void run(){ /*neki kod*/}
    	};
    Thread t = new Thread(r);
    
  3. Thread t = new Thread();
    
  4. public class Nit extends Thread {
    	public void run(){ /*neki kod*/ }
    }
    Nit t = new Nit();
    
  5. Thread t = new Thread() {
    	public void run(){ /*neki kod*/ }
    };
    

3. zadatak

Koji od sledećih su korektni načini da se upotrebi Lock?

  1. public void criticalSection() {
    	lock.lock();
    	try {
    		//...
    	} finally {
    		lock.unlock();
    	}
    }
    
  2. public synchronized void criticalSection() {
    	lock.lock();
    	//...
    	lock.unlock();
    }
    
  3. public void criticalSection() {
    	lock.lock();
    	//...
    	lock.unlock();
    }
    
  4. public synchronized void criticalSection() {
    	lock.lock();
    	try {
    		//...
    	} finally {
    		lock.unlock();
    	}
    }
    

Postavka

U zavisnosti od grupe bilo je potrebno rešiti jedan od sledećih problema:

1. Rešiti Unisex Bathroom problem koristeći ReentrantLock. Potrebno je da program bude maksimalno konkurentan.

2. Rešiti Atomic Broadcast problem koristeći AtomicInteger. Potrebno je da program bude maksimalno konkurentan.

Rešenje za Unisex Bathroom

Ispod je rešenje za Unisex Bathroom.

Test.java

package UnisexBathLocksLab1PrvaGrupa;

public class Test {
	
	public static void main(String[] args) {
		
		int m = 5;
		int w = 5;
		
		int N = 4;
		
		Bathroom  b = new Bathroom(N);
		
		Thread mt[] = new Thread[m];
		Thread wt[] = new Thread[m];
		
		for(int i = 0; i < m; i++) {
			mt[i] = new Man(b);
			mt[i].start();
		}
		
		for(int i = 0; i < w; i++) {
			wt[i] = new Woman(b);
			wt[i].start();
		}
		
	}

}

Woman.java

package UnisexBathLocksLab1PrvaGrupa;

public class Woman extends Thread{
	
	public int id;
	public static int running_id = 0;
	
	Bathroom bath;
	
	public Woman(Bathroom bath) {
		id = running_id++;
		this.bath = bath;
		
	}
	
	@Override
	public void run() {
		while(true) {
			
			bath.w_enter(id);
			
			try {
				Thread.sleep((int)(Math.random() * 1000));
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
			bath.w_exit(id);
			
		}
	}
	
}

Man.java

package UnisexBathLocksLab1PrvaGrupa;

public class Man extends Thread{
	
	public int id;
	public static int running_id = 0;
	
	Bathroom bath;
	
	public Man(Bathroom bath) {
		id = running_id++;
		this.bath = bath;
		
	}
	
	@Override
	public void run() {
		while(true) {
			
			bath.m_enter(id);
			
			try {
				Thread.sleep((int)(Math.random() * 1000));
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
			bath.m_exit(id);
			
		}
	}
	
}

Bathroom.java

package UnisexBathLocksLab1PrvaGrupa;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Bathroom {

	private int woman_cnt = 0;
	private int man_cnt = 0;

	private int capacity = 0;

	Lock lock = new ReentrantLock();
	Condition all = lock.newCondition();

	private int ticket = 0;
	private int next = 0;

	public Bathroom(int N) {
		this.ticket = 0;
		this.next = 0;
		this.man_cnt = 0;
		this.woman_cnt = 0;
		this.capacity = N;
	}

	public void m_enter(int id) {
		lock.lock();

		try {
			int my_ticket = ticket++;
			
			System.out.println("Man(" + id + ") waiting");
			while (my_ticket != next || woman_cnt > 0 || man_cnt >= capacity) {
				all.awaitUninterruptibly();
			}

			System.out.println("Man(" + id + ") entered");

			man_cnt += 1;
			this.next += 1;

		} finally {
			lock.unlock();
		}

	}

	public void m_exit(int id) {

		lock.lock();

		try {
			System.out.println("Man(" + id + ") left");
			man_cnt -= 1;
			all.signalAll();
		} finally {
			lock.unlock();
		}

	}

	public void w_enter(int id) {
		lock.lock();

		try {
			int my_ticket = ticket++;
			
			
			System.out.println("Woman(" + id + ") waiting");
			while (my_ticket != next || man_cnt > 0 || woman_cnt >= capacity) {
				all.awaitUninterruptibly();
			}

			System.out.println("Woman(" + id + ") entered");

			woman_cnt += 1;
			next += 1;

		} finally {
			lock.unlock();
		}

	}

	public void w_exit(int id) {

		lock.lock();

		try {
			System.out.println("Woman(" + id + ") left");
			woman_cnt -= 1;
			all.signalAll();
		} finally {
			lock.unlock();
		}
	}

}

Rešenje za AtomicInteger

Ispod je rešenje za Atomic Broadcast sa jednoelementnim baferom.

Consumer.java

import java.util.concurrent.atomic.AtomicInteger;

public class Consumer extends Thread {
    private static int static_id = 0;
    private AtomicInteger buffer;
    private AtomicInteger[] read_count;
    private int id;

    public Consumer(AtomicInteger buffer, AtomicInteger[] read_count) {
        this.buffer = buffer;
        this.read_count = read_count;
        this.id = static_id++;
    }


    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            while (read_count[id].get() == 1) {
                Thread.onSpinWait();
            }


            int element = buffer.get();
            System.out.println("Consumer " + id + " read element " + element);

            read_count[id].set(1);
            try {
                Thread.sleep((int) (Math.random() * 2000));
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

Producer.java

import java.util.concurrent.atomic.AtomicInteger;

public class Producer extends Thread {

    private final int consumer_count;
    private AtomicInteger buffer;
    private AtomicInteger[] read_count;

    public Producer(AtomicInteger buffer, AtomicInteger[] read_count, int consumer_count) {
        this.buffer = buffer;
        this.read_count = read_count;
        this.consumer_count = consumer_count;

    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            for (int j = 0; j < consumer_count; j++) {
                while(read_count[j].get() == 0)
                    Thread.onSpinWait();
            }
            int random_element = (int) (Math.random() * 10);
            System.out.println("Producer produced element: "+random_element);
            buffer.set(random_element);

            for (int j = 0; j < consumer_count; j++) {
                read_count[j].set(0);
            }
        }

    }
}

Kod za testiranje funkcionalnosti:

Test.java

import java.util.concurrent.atomic.AtomicInteger;

public class Test {

    private static final int CONSUMER_COUNT = 10;

    public static void main(String[] args) {

        AtomicInteger[] read_count = new AtomicInteger[CONSUMER_COUNT];
        AtomicInteger buffer = new AtomicInteger(0);


        Consumer[] consumers = new Consumer[CONSUMER_COUNT];
        Producer producer = new Producer(buffer, read_count, CONSUMER_COUNT);

        for (int i = 0; i < CONSUMER_COUNT; i++) {
            read_count[i] = new AtomicInteger(1);
            consumers[i] = new Consumer(buffer, read_count);
            consumers[i].start();
        }

        producer.start();


    }
}