КДП/Лаб 1 2024
Прва лабораторијска вежба 2024. године одржана је 29. i 30. априла и носила је 10 бодова (3 бода Moodle 7 бодова задатак). Укупно је било 4 групе.
Улазни тест Група 1 и 2
1. задатак
Уколико нит А позове a(), а нит Б позове b(), шта ће се десити са нити Б?
public class A {
public synchronized void a() {
//neki kod ...
}
public synchronized void b() {
//neki kod..
}
A obj = new A();
}
Одговор: Зауставиће се док се не изврши a()
2. задатак
Који од следећег су валидни начини да се иницијализује нит?
Runnable r = new Runnable() { public void run(){ /*neki kod*/ } };
Runnable r = new Runnable() { public void run(){ /*neki kod*/} }; Thread t = new Thread(r);
Thread t = new Thread();
public class Nit extends Thread { public void run(){ /*neki kod*/ } } Nit t = new Nit();
Thread t = new Thread() { public void run(){ /*neki kod*/ } };
3. задатак
Прва нит извршава readMethod()
и закључала је readLock
. Друга нит је позвала writeMethod()
.
public class LockExample {
private static final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
public void readMethod() {
rwLock.readLock().lock();
try {
// Neki kod...
} finally {
rwLock.readLock().unlock();
}
}
public void writeMethod() {
if (!rwLock.isWriteLocked()) {
rwLock.writeLock().lock();
try {
// Neki kod..
} finally {
rwLock.writeLock().unlock();
}
}
}
}
Чему служи параметар у конструктору ReentrantReadWriteLock
?
Одговор: FIFO Fairness
Шта се дешава са другом нити?
Одговор: Блокира се на writeLock
Улазни тест Групe 3
1. задатак
Када нит T увек трајно престаје да се извршава?
- Када нит позове wait над неким објектом.
- Када се заврши њена run метода.
- Када позове своју interrupt методу.
- Ниједан од понуђених одговора.
2. задатак
Који од наведених исказа су тачни?
ArrayBlockingQueue
je pogodan za rešavanje ProducerConsumer problema.- Za implementaciju
ProducerConsumer
problema, može se koristiti par metodaadd(E e) i remove()
objekta tipaBlockingQueue
, bez dodatnih sinhronizacionih elemenata/direktiva. - Za implementaciju
ProducerConsumer
problema, može se koristiti par metodaputFirst(E e) i takeLast()
objekta tipaBlockingDeque
, bez dodatnih sinhronizacionih elemenata/direktiva. - Za implementaciju
ProducerConsumer
problema, može se koristiti par metodatransfer(E e) i take()
objekta tipaTransferQueue
, bez dodatnih sinhronizacionih elemenata/direktiva. - Za implementaciju
ProducerConsumer
problema, može se koristiti par metodaputFirst(E e) i takeFirst()
objekta tipaBlockingDeque
, bez dodatnih sinhronizacionih elemenata/direktiva.
3. задатак
Уколико нит threadA тренутно извршава методу обј.а(), а потом нит threadB позива методу обј.б(), који од понуђених одговора су тачни, уколико је дат следећи део кода?
public class A {
private ReentrantReadWriteLock rw = new ReentrantReadWriteLock(true);
public void a() {
try {
rw.readLock().lock();
// kritična sekcija A... // <- threadA
} finally {
rw.readLock().unlock();
}
}
public void b() {
try {
if (rw.getReadLockCount()==0) {
rw.writeLock().lock();
}
// kritična sekcija B...
} finally {
rw.writeLock().unlock();
}
}
}
A obj = new A();
- Десиће се грешка приликом извршавања.
- Аргумент конструктора ReentrantReadWriteLock означава да могу две нити истовремено да позивају закључавање.
- Нити А и Б могу истовремено да извршавају критичне секције у методама a() и b() (респективно).
- Нит Б ће бити блокирана док нит А не заврши позив методе a().
- Аргумент конструктора ReentrantReadWriteLock означава да ли ће се буђење нити обављати по FIFO принципу.
- Нит Б неће извршити закључавање, јер услов if-a није испуњен.
Улазни тест Групe 4
1. задатак
Који од следећег су валидни начини да се иницијализује нит?
Runnable r = new Runnable() { public void run(){ /*neki kod*/ } };
Runnable r = new Runnable() { public void run(){ /*neki kod*/} }; Thread t = new Thread(r);
Thread t = new Thread();
public class Nit extends Thread { public void run(){ /*neki kod*/ } } Nit t = new Nit();
Thread t = new Thread() { public void run(){ /*neki kod*/ } };
2. задатак
Који од наведених исказа су тачни?
ArrayBlockingQueue
je pogodan za rešavanje ProducerConsumer problema.- Za implementaciju
ProducerConsumer
problema, može se koristiti par metodaadd(E e) i remove()
objekta tipaBlockingQueue
, bez dodatnih sinhronizacionih elemenata/direktiva. - Za implementaciju
ProducerConsumer
problema, može se koristiti par metodaputFirst(E e) i takeLast()
objekta tipaBlockingDeque
, bez dodatnih sinhronizacionih elemenata/direktiva. - Za implementaciju
ProducerConsumer
problema, može se koristiti par metodatransfer(E e) i take()
objekta tipaTransferQueue
, bez dodatnih sinhronizacionih elemenata/direktiva. - Za implementaciju
ProducerConsumer
problema, može se koristiti par metodaputFirst(E e) i takeFirst()
objekta tipaBlockingDeque
, bez dodatnih sinhronizacionih elemenata/direktiva.
3. задатак
Како правилно осигурати међусобно искључивање критичне секције?
- Овај задатак није решен. Помозите SI Wiki тако што ћете га решити.
Поставка Свих Група
У зависности од групе било је потребно решити један од следећих проблема:
1. Решити Atomic Broadcast
проблем користећи AtomicInteger
и опционо Semaphore
. Бафер садржи B елемената. Потребно је да програм буде максимално конкурентан и отпоран на прекиде.
2. Решити H2O
проблем користећи CyclicBarrier
. Потребно је да програм буде максимално конкурентан и отпоран на прекиде.
3. Решити Dining Philosophers
проблем користећи AtomicInteger
и регионе. филозофи који су раније изразили жељу за храном треба раније да буду опслужени . Потребно је да програм буде максимално конкурентан и отпоран на прекиде.
4. Решити Child Care
проблем користећи ConcurrentLinkedQueue
и друге произвољне синхронизационе директиве. Родитељ доводи једно или више деце у обданиште и чека све док се не појави место, како би оставио сву децу одједном и отишао. Родитељ може и да одведе једно или више деце, такође одједном. Мора се поштовати редослед доласка родитеља који остављају децу и васпитачица које одлазе са посла. Потребно је да програм буде максимално конкурентан и отпоран на прекиде.
Решење за Atomic Broadcast
Test.java
package rs.ac.bg.etf.kdp.lab12024G1;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;
public class Test {
private static final int consumersCount=3;
private static final int b=5;
public static void main(String[] args) {
AtomicInteger[][] reads = new AtomicInteger[b][consumersCount];
Semaphore mutex = new Semaphore(1);
AtomicInteger[] buffer = new AtomicInteger[b];
for (int i = 0; i < buffer.length; i++)
buffer[i] = new AtomicInteger(0);
Consumer[] consumers = new Consumer[consumersCount];
Producer p = new Producer(consumersCount, buffer, reads,b,mutex);
p.start();
for (int i = 0; i < b; i++)
for(int j=0;j<consumersCount;j++)
reads[i][j] = new AtomicInteger(1);
for (int i = 0; i < consumersCount; i++) {
consumers[i] = new Consumer(buffer, reads,b,mutex,i);
consumers[i].start();
}
}
}
Producer.java
package rs.ac.bg.etf.kdp.lab12024G1;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;
public class Producer extends Thread {
private final int consumers;
private AtomicInteger[] buffer;
private AtomicInteger[][] reads;
private Semaphore mutex;
private int b;
public Producer(int consumers, AtomicInteger[] buffer, AtomicInteger[][] reads, int bb, Semaphore mutex) {
this.consumers = consumers;
this.buffer = buffer;
this.reads = reads;
b=bb;
this.mutex = mutex;
}
@Override
public void run() {
for (int i = 0; i <b; i++) {
for (int j = 0; j < consumers; j++)
while(reads[i][j].get() == 0)
Thread.onSpinWait();
int rand = (int)(Math.random() * 10);
System.out.println("Producer produced element: " + rand );
mutex.acquireUninterruptibly();
buffer[i].set(rand);
mutex.release();
mutex.acquireUninterruptibly();
for (int j2 = 0; j2 < consumers; j2++)
reads[i][j2].set(0);
mutex.release();
}
}
}
Consumer.java
package rs.ac.bg.etf.kdp.lab12024G1;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;
public class Consumer extends Thread {
private int id;
private AtomicInteger[][] reads;
private AtomicInteger[] buffer;
private Semaphore mutex;
private int b;
public Consumer(AtomicInteger[] buff, AtomicInteger[][] r, int bb,Semaphore mutex, int i) {
buffer = buff;
reads=r;
id=i;
this.mutex = mutex;
b=bb;
}
@Override
public void run() {
for (int i = 0; i < b; i++) {
while(reads[i][id].get() == 1)
Thread.onSpinWait();
mutex.acquireUninterruptibly();
int elem = buffer[i].get();
System.out.println("Consumer "+id+" consumed element "+elem +"from place "+i);
reads[i][id].set(1);
mutex.release();
try {
sleep((int)(Math.random()*2000));
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
Решење за H2O
Test.java
package H20;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.atomic.AtomicInteger;
public class Test {
public static void main(String[] args) {
int cnt = 10;
Barrier barrier = new Barrier(new CyclicBarrier(3));
Hydrogen[] h = new Hydrogen[cnt*2];
Oxygen[] o = new Oxygen[cnt];
for(int i = 0; i < cnt; i++) {
o[i] = new Oxygen(barrier);
h[2*i] = new Hydrogen(barrier);
h[2*i + 1] = new Hydrogen(barrier);
o[i].start();
h[2*i].start();
h[2*i+1].start();
}
}
}
Oxygen.java
package H20;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.Semaphore;
public class Oxygen extends Thread {
Barrier barrier;
Oxygen(Barrier b){
barrier = b;
}
@Override
public void run() {
while(true) {
try {
Thread.sleep((int)(Math.random() * 4000));
} catch (InterruptedException e) {}
barrier.oxygen.acquireUninterruptibly();
barrier.oCount++;
try {
System.out.println("Kiseonik pristigao na barijeru");
if(barrier.barrier.await() == 0) {
System.out.println("\nFORMIRANJE VODE!\n");
barrier.hCount = 0;
barrier.oCount = 1;
barrier.hydrogen.release(2);
barrier.oxygen.release(1);
}
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}
Hydrogen.java
package H20;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.Semaphore;
public class Hydrogen extends Thread {
Barrier barrier;
Hydrogen(Barrier b){
barrier = b;
}
@Override
public void run() {
while(true) {
try {
Thread.sleep((int)(Math.random() * 4000));
} catch (InterruptedException e) {}
barrier.hydrogen.acquireUninterruptibly();
barrier.hCount++;
try {
System.out.println("Vodonik pristigao na barijeru");
if(barrier.barrier.await() == 0) {
System.out.println("\nFORMIRANJE VODE!\n");
barrier.hCount = 0;
barrier.oCount = 1;
barrier.hydrogen.release(2);
barrier.oxygen.release(1);
}
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}
Barrier.java
package H20;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.Semaphore;
public class Barrier {
CyclicBarrier barrier;
Semaphore hydrogen, oxygen;
int hCount, oCount;
Barrier(CyclicBarrier cb){
barrier = cb;
hCount = 0;
oCount = 0;
hydrogen = new Semaphore(2);
oxygen = new Semaphore(1);
}
}
Решење за Dining Philosophers
Test.java
package rs.ac.bg.etf.kdp.lab12024G3;
import java.util.concurrent.atomic.AtomicInteger;
public class Test {
public static final int N = 5;
public static void main(String[] args) {
Philosopher[] philosophers = new Philosopher[N];
AtomicInteger[] forks = new AtomicInteger[N];
for (int i = 0; i < forks.length; i++)
forks[i] = new AtomicInteger(1);
Table table = new Table();
for (int i = 0; i < N; i++) {
philosophers[i] = new Philosopher(forks, i, N, table);
philosophers[i].start();
}
}
}
Table.java
package rs.ac.bg.etf.kdp.lab12024G3;
import java.util.concurrent.atomic.AtomicInteger;
public class Table {
AtomicInteger ticket;
int next;
public Table() {
ticket = new AtomicInteger(0);
next = 0;
}
}
Philosopher.java
package rs.ac.bg.etf.kdp.lab12024G3;
import java.util.concurrent.atomic.AtomicInteger;
public class Philosopher extends Thread {
AtomicInteger[] forks;
int id,left,right,N,myTicket;
Table t;
public Philosopher(AtomicInteger[] forks, int id, int n,Table table) {
this.forks = forks;
this.id = id;
N = n;
left = id;
right = (id+1)%n;
t = table;
}
@Override
public void run() {
while(true) {
int choice = (int)(Math.random() * 2);
switch (choice) {
case 0: {
eat();
break;
}
case 1:{
think();
break;
}
default:
throw new IllegalArgumentException("Unexpected value: " + choice);
}
}
}
public void think() {
System.out.println("Philosopher "+id+" thinking");
try {
sleep((int)(Math.random() * 3000));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void eat() {
myTicket = t.ticket.getAndIncrement();
synchronized (forks) {
System.out.println("Philosopher "+id+" wants to eat");
while(forks[left].intValue() == 0 || forks[right].intValue() == 0 || myTicket != t.next)
try {
forks.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Philosopher "+id+" started eating");
t.next++;
forks[left].set(0);
forks[right].set(0);
}
try {
sleep((int)(Math.random() * 2000));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized (forks) {
System.out.println("Philosopher "+id+" finished eating");
forks[left].set(1);
forks[right].set(1);
forks.notifyAll();
}
}
}
Решење за Child Care
- Овај задатак није решен. Помозите SI Wiki тако што ћете га решити.