This is kind of a big question.
I am attempting to create an ordered multiple producer and single consumer scenario in Java. It is ordered in the sense that after producer1, only producer2 gets control of the queue, after which producer3, after which producer1 again and so on and so forth. Just to check if that will work under every scenario, I provided the three producers with three different priorities
producer1 - Thread.NORM_PRIORITY - 4
producer2 - Thread.NORM_PRIORITY + 5
producer3 - Thread.NORM_PRIORITY
Now instead of printing what is being put in the queue and what is being consumed, I'm keeping a counter to count how many times each of the producer threads are being handed control of the queue and in what order, and printing those counts in the consumer thread.
Code is provided after the outputs.
I am confused by one particular behaviour of the threads, the code posted below works as I wanted it to, but if I replace this
while(flag==false)
wait();
if(getIndex()!=next)
return;
in the put() function of q.java, with this
while(flag==false && getIndex()!=next)
wait();
The producer threads are being handed control of the queue erratically. Like with the first code snippet, I am getting the following output, for producers 1,2 and 3 respectively
125 125 125
126 125 125
126 126 125
126 126 126
Producer1 is getting control of the queue first, then 2 then 3, and then 1 again.
But with the alternate option I am getting this output
2 6 8
2 6 8
2 6 8
The same producer keeps getting control of the queue.
Shouldn't the waiting thread NOT gain control of the queue unless it's index matches with the index of the thread which is supposed to get control of the q, like if next is 2, and producer3 is handled control of the queue, shouldn't it go into wait because of the while condition, and the queue be free to be approached by some other thread again, the process repeating until producer2 gets it?
QUEUE
import java.util.*;
class q
{
private volatile int size;
private volatile int clicks[];
private volatile boolean flag;
private volatile int next;
public q(int size)
{
this.size = size;
clicks = new int[size+1];
flag = true;
next = 1;
}
private synchronized int getIndex()
{
String name = Thread.currentThread().getName();
return (int)(name.charAt(name.length()-1))-48;
}
private synchronized void show()
{
//System.out.println("Got control -> "+name+" for index "+index);
if(flag==true)
{
int index = getIndex();
/*
System.out.println("Control provided to "+index);
Scanner s = new Scanner(System.in);
System.out.println("Press enter to continue");
String c = s.next();
*/
clicks[index]+=1;
next = (index%size)+1;
//System.out.println("Provide control to "+next);
}
else
{
int i;
for(i = 1;i<=size;i++)
System.out.print(clicks[i]+" ");
System.out.println();
}
}
public synchronized void put()
{
try
{
while(flag==false)
wait();
if(getIndex()!=next)
return;
show();
flag = false;
notify();
}
catch(Exception e)
{
System.out.println("Exception caught - "+e);
}
}
public synchronized void get()
{
try
{
while(flag==true)
wait();
show();
flag = true;
notifyAll();
}
catch(Exception e)
{
System.out.println("Exception caught - "+e);
}
}
}
PRODUCER
class producer implements Runnable
{
private q queue;
public producer(q queue)
{
this.queue = queue;
}
public void run()
{
try
{
//int i;
while(true)
queue.put();
}
catch(Exception e)
{
System.out.println("Exception caught - "+e);
}
}
}
CONSUMER
class consumer implements Runnable
{
private q queue;
public consumer(q queue)
{
this.queue = queue;
}
public void run()
{
try
{
while(true)
queue.get();
}
catch(Exception e)
{
System.out.println("Exception caught - "+e);
}
}
}
TESTCLASS
class testclass
{
private q queue;
private producer p1; //lowest priority
private producer p2; //highest priority
private producer p3; //normal priority
private consumer c;
private Thread pt1;
private Thread pt2;
private Thread pt3;
private Thread ct;
public testclass()
{
queue = new q(3);
p1 = new producer(queue);
p2 = new producer(queue);
p3 = new producer(queue);
c = new consumer(queue);
pt1 = new Thread(p1,"producer1");
pt2 = new Thread(p2,"producer2");
pt3 = new Thread(p3,"producer3");
ct = new Thread(c,"consumer");
}
public void begin()
{
pt2.setPriority(Thread.NORM_PRIORITY + 5);
pt1.setPriority(Thread.NORM_PRIORITY - 4);
//pt3.setPriority(Thread.NORM_PRIORITY - 3);
pt1.start();
pt2.start();
pt3.start();
ct.start();
}
public static void main(String args[])
{
try
{
testclass t = new testclass();
t.begin();
}
catch(Exception e)
{
System.out.println("Exception caught - "+e);
}
}
}
It looks like you are dealing with threads and concurrency but not.
You are dealing with logical operators:
Your code
while(flag==false && getIndex()!=next)
wait();
If flag is true then your logical expression will be false and the execution will go on. What you really need is:
while(flag==false || getIndex()!=next)
wait();
There are so many things wrong with this code, it is hard to tell where the actual problem is. I strongly suggest that you upgrade your knowledge on threading first by reading a good book on the topic.
The major problem here is that you confuse thread priority with order of execution. In general the order of execution with threads is undefined, and unless you enforce the order, there is no order. The only thing that thread priority does is to specify which thread is put on hold if there are more running threads than CPUs that can execute them. It will not enforce any order of execution otherwise.
I.E. when several threads try to enter a synchronized function, then one of them is granted access, but which one that will be is not specified. It could be the high priority thread, but it could also be any other as well. Since all your functions are synchronized all threads are constantly put on hold, therefore even thread priority won't do a thing, because most of the time threads are waiting on their lock anyways.
Related
I have a small project to synchronize multiple (two classes: ships, cars with a few instances with shared bufor class called Harbour) threads at the same time. They will be performing certain action on it. But I can't start with that until I synchronized the threads named "cars" in the Harbour. The Harbour has limited capacity and if this capacity is reached the "car" threads should be waiting until they will get signal that there's a free space to enter. I've used Retrant Lock with Condition but it doesn't work as I think.
public class Harbour {
final Lock protectNr;
final Condition protectNrCon;
int capacity;
int nrOfCars;
public Harbour(int capacity) {
this.capacity = capacity;
this.protectNr = new ReentrantLock();
this.protectNrCon = protectNr.newCondition();
}
public void carEnterHarbour(String name) {
try {
protectNr.lock();
if (this.nrOfCars == this.capacity)
protectNrCon.await();
nrOfCars++;
System.out.println(name + " enters");
System.out.println("Number of cars:" + this.nrOfCars);
protectNr.unlock();
} catch (InterruptedException e) {
System.out.println("Error");
}
}
public void carLeavingHarbour(String name) {
try {
protectNr.lock();
this.nrOfCars--;
protectNrCon.signal();
System.out.println(name + " leaving");
System.out.println("Number of cars:" + this.nrOfCars);
} finally {
protectNr.unlock();
}
}
}
public class Car extends Thread {
Harbour harbour;
public Car(Harbour harbour, String name) {
super(name);
this.harbour = harbour;
}
public void run() {
for (int i = 0; i < 10; i++) {
harbour.carEnterHarbour(getName());
harbour.carLeavingHarbour(getName());
}
}
}
public class Test {
public static void main(String[] args) throws InterruptedException {
int harbourCapacity = 20;
final Harbour harbour = new Harbour(harbourCapacity);
int nrOfCars = 500;
Car[] cars = new Car[nrOfCars];
for (int i = 0; i < nrOfCars; i++)
cars[i] = new Car(harbour, "Car-" + i);
for (int i = 0; i < nrOfCars; i++)
cars[i].start();
for (int i = 0; i < nrOfCars; i++)
cars[i].join();
}
}
What I was expecting after executing this code:
Car-386 leaving
Number of cars:**19**
Car-300 enters
Number of cars:**20**
Car-300 leaving
Number of cars:**19**
What I got:
Car-386 leaving
Number of cars:**20**
Car-300 enters
Number of cars:**21**
Car-295 enters
Number of cars:**22**
I also try to change int capacity to volatile int capacity and add some busy waiting but didn't work at all.
It looks like Threads are not block on Condition and I wonder why is this happening?
The documentation for Condition warns that spurious wakeups might occur (emphasis mine):
When waiting upon a Condition, a "spurious wakeup" is permitted to occur, in general, as a concession to the underlying platform semantics. This has little practical impact on most application programs as a Condition should always be waited upon in a loop, testing the state predicate that is being waited for. An implementation is free to remove the possibility of spurious wakeups but it is recommended that applications programmers always assume that they can occur and so always wait in a loop.
Your code doesn't honor that warning.
Your carEnterHarbour() must take this possibility of spurious wakeups into account and needs
while(this.nrOfCars == this.capacity){
protectNrCon.await();
}
instead of the simple if statement.
Depending on your requirements it might be easier to use a Semaphore:
public class Harbour {
final Semaphore slots;
public Harbour(int capacity){
this.slots = new Semaphore(capacity);
}
public void carEnterHarbour(String name) {
try{
slots.acquire();
}catch (InterruptedException e){
System.out.println("Error");
}
}
public void carLeavingHarbour(String name) {
slots.release();
}
}
Note that when using a Semaphore you don't have those locks in place when entering / leaving the Harbour and therefore it is difficult to get that ordered "car entering" / "car leaving" output together with the number of currently available slots.
In the carEnterHarbour method, you are calling await() on the protectNrCon condition, which causes the current thread to wait until it is signaled. However, you are not calling signal() anywhere in the carEnterHarbour method. This means that once a thread enters the if block, it will always wait indefinitely on the condition.
You should consider calling signal() on the protectNrCon condition after you increment nrOfCars and print the message, so that other threads waiting on the condition can be unblocked.
Additionally, you should call await() in a loop to ensure that the thread waits until the condition is true, rather than waiting indefinitely. Here is an example of how you can modify the carEnterHarbour method:
public void carEnterHarbour(String name) {
try {
protectNr.lock();
while (this.nrOfCars == this.capacity) {
protectNrCon.await();
}
nrOfCars++;
System.out.println(name+" enters");
System.out.println("Number of cars:" + this.nrOfCars);
protectNrCon.signal();
} catch (InterruptedException e) {
System.out.println("Error");
} finally {
protectNr.unlock();
}
}
This question already has answers here:
How threads are executed in the memory?
(2 answers)
Closed 2 years ago.
This is a simplified version of the problem. Given n number of threads, each printing a constant number all the time. For example, Thread-1 should always print 1, Thread-2 should always print 2 and so on...
How to ensure, the threads are executed in order i.e. the output should be as below:
Thread-1: 1
Thread-2: 2
Thread-3: 3
.
.
.
Thread-n: n
I have a naïve solution to do it through wait()/notify() but I guess there might be a better solution than that. Perhaps, using Semaphore maybe? I don't know.
Update:
Based on the answers received, I think I was not very clear. There are some constraints:
All threads should start at once (assume we don't really have control on that)
Once all the threads start, there should be some sort of communication between the threads to execute in order.
This sequentially execution of thread can be handled beautifully using Thread.join() method. To handle it properly, you may have to create MyRunnable(or, use any name you prefer) which implements Runnable interface. Inside MyRunnable, you can inject a parent Thread, and call parent.join() at top of MyRunnable.run() method. The code is given below:
public class SequentialThreadsTest {
static class MyRunnable implements Runnable {
static int objCount; // to keep count of sequential object
private int objNum;
private Thread parent; // keep track of parent thread
MyRunnable(Thread parent) {
this.parent = parent;
this.objNum = objCount + 1;
objCount += 1;
}
#Override
public void run() {
try {
if(parent != null) {
parent.join();
}
System.out.println("Thread-" + objNum + ": " + objNum);
} catch(InterruptedException e) {
e.printStackTrace();
// do something else
} finally {
// do what you need to do when thread execution is finished
}
}
}
public static void main(String[] args) {
int n = 10;
Thread parentThread = null;
for(int i=0; i<n; i++) {
Thread thread = new Thread(new MyRunnable(parentThread));
thread.start();
parentThread = thread;
}
}
}
And the output is:
Thread-1: 1
Thread-2: 2
Thread-3: 3
Thread-4: 4
Thread-5: 5
Thread-6: 6
Thread-7: 7
Thread-8: 8
Thread-9: 9
Thread-10: 10
You haven't specified many details, but if you only want serializable thread execution you can wait for previous thread to finish and then print. Something like this:
public static void main(String[] args) {
Thread thread = null;
for (int i = 0; i < 10; i++) {
int index = i;
Thread previousThread = thread;
thread = new Thread(() -> {
if (previousThread != null) {
try {
previousThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(index);
});
thread.start();
}
}
Try making a queue - this will do exactly what you want. Simply change the value of n to however many threads you have, and add all the threads sequentially (only once). If ever you want to stop the threads from executing, all you have to do is add end to the queue. Obviously, for a larger project, you will need to modify this code a little bit (I would recommend replacing the main method with a class initializer and pass the LinkedBlockingQueue as a pre-built argument)
import java.util.concurrent.LinkedBlockingQueue;
public class HelloWorld{
private static int n = 2;
private static LinkedBlockingQueue<Thread> queue = new LinkedBlockingQueue<>(n+1);
static Thread a = new Thread(()->{
System.out.print("a");
});
static Thread b = new Thread(()->{
System.out.print("b");
});
static Thread end = new Thread(()->{
break_ = true;
});
public static final int END = 20;//this and the counter are just here so the code doesn't run forever
public static volatile int i = 0;
public static volatile boolean break_ = false;
public static void main(String []args){
queue.add(a);
queue.add(b);
//queue.add(end);
outerloop:
while(true){
Thread toBeRun = queue.poll();
try{
toBeRun.run();
queue.add(toBeRun);
i++;
if(i>=END || break_){//i>=END does not need to be here, it's just to stop it from running forever in this example
break;
}
}catch(NullPointerException e){
break;
}
}
}
}
Note: This uses java 8 lambdas. If you're using an older version of java, you will need to create the threads using the run method.
I was trying to learn multi threading, and was trying out a simple producer/consumer pattern with wait and notify. When i split the pattern with two consume and one produce i get an ArrayIndexOutOfBounds Exception which is not clear. The issue does not occur always it occurs at times. I am using a I3 processor.
I have tried added an if block to check if the count variable is going below or above the declared size and still the issue persists.
private static Object key = new Object();
private static int[] buffer;
private volatile static Integer count;
static class Consumer {
void consume() {
synchronized (key) {
if (isEmpty()) {
try {
key.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
buffer[--count] = 0;
key.notify();
}
}
public boolean isEmpty() {
return count == 0;
}
}
static class Producer {
void produce() {
synchronized (key) {
if (isFull()) {
try {
key.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
buffer[count++] = 1;
key.notify();
}
}
public boolean isFull() {
return count == buffer.length;
}
}
public static void main(String[] args) throws InterruptedException {
buffer = new int[10];
count = 0;
Producer producer = new Producer();
Consumer consumer = new Consumer();
Runnable produce = () -> {
for (int i = 0; i < 1500; i++)
producer.produce();
System.out.println("Done producing");
};
Runnable consume = () -> {
for (int i = 0; i < 1300; i++)
consumer.consume();
System.out.println("Done consuming");
};
Thread producerWorker = new Thread(produce);
Thread consumerWorker = new Thread(consume);
producerWorker.start();
consumerWorker.start();
//consumerWorker.join();
Runnable checker = () -> {
System.out.println("Lanched Delayed Consumer");
for (int i = 0; i < 200; i++)
consumer.consume();
};
Thread delayedConsumer = new Thread(checker);
delayedConsumer.start();
producerWorker.join();
System.out.println("Data in Buffer " + count);
}
}
Expected it to be :
Lanched Delayed Consumer
Done consuming
Done producing
Data in Buffer 0
but got :
Lanched Delayed Consumer
Exception in thread "Thread-1" Exception in thread "Thread-0" java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 10
at com.multi.thread.waitandnotify.WaitNotifyRunner$Consumer.consume(WaitNotifyRunner.java:27)
at com.multi.thread.waitandnotify.WaitNotifyRunner.lambda$1(WaitNotifyRunner.java:78)
at java.base/java.lang.Thread.run(Thread.java:835)
java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 10
at com.multi.thread.waitandnotify.WaitNotifyRunner$Producer.produce(WaitNotifyRunner.java:55)
at com.multi.thread.waitandnotify.WaitNotifyRunner.lambda$0(WaitNotifyRunner.java:73)
at java.base/java.lang.Thread.run(Thread.java:835)
Data in Buffer 0
The problem is that:
you have only one wait condition that you share for both the "full" and the "empty" state
you're running two consumer threads ("consumerWorker" and "delayedConsumer") and one producer ("producerWorker")
you're not re-checking the condition in a while-loop like you should
A possible thing that happens is:
Both consumer threads see that the buffer is empty
The producer thread puts one item in the buffer, and notifies.
A single consumer thread wakes up and processes one item. The buffer is now empty. It then notifies.
The second consumer thread wakes up (instead of the producer like you intended), doesn't check whether the buffer is empty, and tries to access the buffer at index -1.
You need to recheck the condition after you wake up from a wait call. Change the if to a while. Here's how to do that for the consumer; you need to do the same for the producer.
void consume() {
synchronized (key) {
while (isEmpty()) {
try {
key.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
buffer[--count] = 0;
key.notify();
}
}
That way the consumer won't get confused by the notify from the other consumer thread.
This is also "recommended" by the documentation of Object.wait:
The recommended approach to waiting is to check the condition being
awaited in a while loop around the call to wait, as shown in the
example below. Among other things, this approach avoids problems that
can be caused by spurious wakeups.
(I quoted "recommended" because it's required to do it this way in order to implement it correctly because wait can also spuriously wake up without a call to notify)
your buffer is of length 10
buffer = new int[10];
so it's obvious whenever your count variable's exceeds array capacity which is 10
private volatile static Integer count;
you will get ArrayIndexOutOfBoundsException
you are producing more and consuming less and consuming less and execution of produce/consume is not sequential , its more like round-robin.
I was trying to write a code that shows the unfairness of ReentrantLock (when ctor is passed fair=false). To my surprise, ReentrantLock was perfectly fair.
My test has the following logic: spawn 20 threads who have an "id" going from 0 to 19. All threads share a ReentrantLock. Then, in chronological order:
Thread 0 locks the lock.
Thread 1 to 19 block on lock(), in order 1, then 2, then 3, .. , then 19
Thread 0 unlocks the lock. This is the first test of fairness, if the lock is fair, thread 1 should get it thereafter
When thread 1 has the lock, he releases it too. Second test of fairness: thread 2 should now get it.
etc
I was expecting that sometimes, a thread gets the lock before another one that was actually waiting for longer. But it never happens
The code:
package jma.test;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.ReentrantLock;
class ThreadTest extends Thread {
private final int id;
private final int totalNbThreads;
private final ReentrantLock lock1;
private final LinkedList<Integer> checkOrder;
ThreadTest(int id, int totalNbThreads, ReentrantLock lock, LinkedList<Integer> checkOrder) {
this.id = id;
this.totalNbThreads = totalNbThreads;
this.lock1 = lock;
this.checkOrder = checkOrder;
}
public void run() {
try {
// This if is to force threads to get to lock() call below in order of their ids.
// Thread 0 should call lock() first, then threads 1, 2, 3, 4 ...
if (this.id == 1) {
while (!lock1.isLocked()) {
// wait for thread 0 to lock it
}
} else if (this.id > 1) {
while (lock1.getQueueLength() != (this.id - 1)) {
// íf we are thread n, we wait for thread 1 to n-1 to enter the wait queue.
}
}
lock1.lock();
if (this.id == 0) {
while (lock1.getQueueLength() != (totalNbThreads - 1)) {
// Wait for all other threads to bloc on lock1.lock() before releasing lock
}
}
checkOrder.add(this.id);
} finally {
lock1.unlock();
}
}
}
public class Main {
private static final int NB_THREADS = 20; // at least 2
// change the boolean to switch between fair or not-fair lock
private static final ReentrantLock lock = new ReentrantLock(false);
private static boolean isLockFair() {
Queue<Thread> allThreads = new LinkedList<>();
LinkedList<Integer> checkOrder = new LinkedList<>();
for (int id=0; id < NB_THREADS; id++) {
allThreads.add(new ThreadTest(id, NB_THREADS, lock, checkOrder));
}
for (Thread t : allThreads) {
t.start();
}
for (Thread t : allThreads) {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int previous = -1;
for (int i : checkOrder) {
if (i != previous + 1) {
System.out.println("not fair: " + i + " got the lock after " + previous);
return false;
}
previous = i;
}
return true;
}
public static void main(String[] args) {
int ctrUnfair = 0;
int nbTest = 10000;
for (int i=0; i<nbTest; i++) {
if (!isLockFair())
ctrUnfair++;
}
System.out.println("unfairness: " + ctrUnfair + "/" + nbTest);
}
}
I assume that, because the thread releasing the lock does not try to get it again, when unlock is called there is no concurrency between the running thread and the blocked threads, so the thread that will get the lock necessarily comes from the wait queue, and the implementation of the wait queue is probably a FIFO. Is it the explanation ?
I was expecting that sometimes, a thread gets the lock before another one that was actually waiting for longer. But it never happens
In my understanding,this happens in the case below.
1.Thread a call unlock,after execute tryRelease but before unparkSuccessor,thread scheduling happens,Thread b start to execute.
2.Thread b call lock,if it is a none fair lock,it will call compareAndSetState and will success,you see though other threads waiting for the lock,but thread b got it,but if it is a fair lock,it will test if current thread is the first thread waiting for the lock ,see hasQueuedPredecessors.
All these comes from the source code AQS and ReentrantLock.
Back to your code,before thread 0 can unlock,all other threads are in the waiting queue,so different with the case above.Hope this helps and if I am wrong,please let me know.
I want to solve dining philosophers problem using java semaphores but I'm stuck. Highest id chopstick should be available but it seems to be always taken and i don't know why. Can anyone tell me where I made mistake?
Fork class:
class Fork {
public static Semaphore fork = new Semaphore(1);
public int id;
Fork(int id) {
this.id = id;
}
public int getId() {
return id;
}
public boolean take() {
return fork.tryAcquire();
}
public void putDown() {
fork.release();
}}
Philosopher class:
class Philosopher extends Thread {
private Fork fork_low;
private Fork fork_high;
private String name;
Philosopher(Fork fork_low, Fork fork_high, String name) {
this.fork_low = fork_low;
this.fork_high = fork_high;
this.name = name;
}
public void run() {
try {
sleep(1000);
} catch (InterruptedException ex) {
}
while (true) {
eat();
}
}
private void eat(){
if(fork_low.take()){
if(fork_high.take()){
try {
sleep(2000); // eating;
} catch (InterruptedException ex) { }
fork_high.putDown();
fork_low.putDown();
}
else{
fork_low.putDown();
}
}
}}
Main:
public static void main(String[] args) {
String[] names = {"Plato", "Aristotle", "Cicero", "Confucius", "Eratosthenes"};
Fork[] fork = new Fork[5];
Philosopher[] philosopher = new Philosopher[5];
for (int i = 0; i < fork.length; i++) {
fork[i] = new Fork(i);
}
for (int i = 0; i < philosopher.length; i++) {
if (i != philosopher.length - 1) {
philosopher[i] = new Philosopher(fork[i], fork[i+1], names[i]);
philosopher[i].start();
} else {
philosopher[i] = new Philosopher(fork[0], fork[i], names[i]);
philosopher[i].start();
}
}
}
You have a deadlock, because the Semaphore is static in the Fork class, which is equivalent to only have one fork available. It works perfectly when you make the Semaphore not static (2 random philosophers running on the same time).
You can observe your threads working in JDK's build in tool jvisualvm.
Here is the same problem solved in C language with explaination
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
//if not used then gives warning for sleep used
//semaphore are basically designed to share the resources
// here the sem_t is the data type for the semaphore
sem_t room;//counting semaphore bcoz here only one instance of room butchair has 4
sem_t spoon[5]; //this is binary semaphore since every spoon has its own instance
void * philosopher(void *);
void eat(int);
int main()
{
int i;
int a[5];
pthread_t tid[5];// threads here are refrence to philosophers or diners bcoz we will have multiple users dining
sem_init(&room,0,4);
//1.pointer to declared semaphore
//2.pshared which has 0,1 value that is if 0 ->shared between threads
// if 1 ->shared between process
//3.value with whch u initalise the semaphore
for(i=0;i<5;i++){
//5 binary semaphore each for individual spoon
sem_init(&spoon[i],0,1);
}
for(i=0;i<5;i++){
a[i]=i;//allow 5 to enter at a time and deadlock occurs so let 4 of them in
pthread_create(&tid[i],NULL,philosopher,(void*)&a[i]);
//1.thread id 2.NULL 3.function 4.what you want to pass to the new thread
//here we pass the address of philosophers number to function
}
for(i=0;i<5;i++){
pthread_join(tid[i],NULL);
}
}
void * philosopher(void * num){
int phil=*(int *)num; //cast the number passed as void to integer
//put sem_wait on both semaphore room and spoon
sem_wait(&room);//checks if resource is available,if then allocates and blocks semaphore
// room is counting semaphore so any is alocated then it decrements the count of total semaphore and
// if all are allocated then it blocks thread and places it on queue untill resource is freed
printf("\nPhilospher number %d has sat on dining table\n",phil);
sem_wait(&spoon[phil]);
sem_wait(&spoon[(phil+1)%5]);
//spoon is binary so if value of semaphore is 1 it is changed to 0 which means semaphore is allocated and cannot be used
eat(phil);
sleep(2);
printf("\nPhilosopher %d has finished eating\n",phil);
//free the semaphores so others in thread can use resources
//returns +ve value on freeing semaphore
//for binary semaphore if queue is empty then change semaphore value to 1 if not empty then remove process from queue and
// get it ready for allocation
sem_post(&spoon[(phil+1)%5]);
sem_post(&spoon[phil]);
sem_post(&room);
}
void eat(int phil){
printf("\nPhilosopher %d is eating now\n",phil);
}