How to do it…

  1.  Define an array of 10 elements:
#define max 10
int stack[max];
  1. Define two mutex objects—one to indicate the pop operation of the stack (pop_mutex), and another to represent the push operation of the stack (push_mutex):
pthread_mutex_t pop_mutex;
pthread_mutex_t push_mutex;
  1. To use the stack, the value of top is initialized to -1:
int top=-1;
  1. Define two variables of the type pthread_t, to store two thread identifiers:
pthread_t tid1,tid2;
  1. Invoke the pthread_create function to create the first thread. The thread is created with the default attributes, and the push function is executed to create the thread:
pthread_create(&tid1,NULL,&push,NULL);
  1. Invoke the pthread_create function again to create the second thread. The thread is created with the default attributes, and the pop function is executed to create this thread:
pthread_create(&tid2,NULL,&pop,NULL);
  1. To indicate that the two threads were created, display the message Both threads are created:
printf("Both threads are created\n");
  1. In the push function, invoke the pthread_mutex_lock method and pass the mutex object push_mutexrelated to the push operation, to it, in order to lock it:
pthread_mutex_lock(&push_mutex);
  1. After a sleep of 2 seconds, the mutex object, that is, meant to invoke the pop operation pop_mutex will be locked by the first thread:
sleep(2);
pthread_mutex_lock(&pop_mutex);
  1. Enter the value to be pushed to the stack:
printf("Enter the value to push: ");
scanf("%d",&n);
  1. The value of top is incremented to 0. To stack[0] location, the value, that is, entered by the user is pushed:
top++;
stack[top]=n;
  1. Invoke pthread_mutex_unlock and pass the mutex object pop_mutex to it to unlock it. Also, the mutex object push_mutex will be unlocked:
pthread_mutex_unlock(&pop_mutex);                                                   pthread_mutex_unlock(&push_mutex);
  1. At the bottom of the push function, display the message Value is pushed to stack:
printf("Value is pushed to stack \n");
  1. In the pop function, the pthread_mutex_lock function is invoked to lock the mutex object push_mutex:
pthread_mutex_lock(&push_mutex);
  1. After a sleep (or delay) of 5 seconds, the pop function will try to lock the pop_mutex object, too. However, the pthread_mutex_lock function will not be invoked, as the thread is kept waiting for the push_mutex object to be unlocked:
sleep(5);
pthread_mutex_lock(&pop_mutex);
  1. The value in the stack pointed to by the pointer top is popped. Because the value of top is 0, the value at the location stack[0] is picked up:
k=stack[top];
  1. Thereafter, the value of top will be decremented by 1 to make it -1 again. The value, that is, popped from the stack will be displayed on the screen:
top--;
printf("Value popped is %d \n",k);
  1. Then, the mutex object pop_mutex will be unlocked, followed by the push_mutex object:
pthread_mutex_unlock(&pop_mutex);
pthread_mutex_unlock(&push_mutex);
  1. In the main function, invoke the pthread_join method twice and pass the thread identifiers that were created in step 1 to it:
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);

The avoiddeadlockst.c program for creating two threads and understanding how a deadlock can be avoided while acquiring locks is as follows:

#include <stdio.h>
#include <pthread.h>
#include<unistd.h>
#include <stdlib.h>

#define max 10
pthread_mutex_t pop_mutex;
pthread_mutex_t push_mutex;
int stack[max];
int top=-1;

void * push(void *arg) {
int n;
pthread_mutex_lock(&push_mutex);
sleep(2);
pthread_mutex_lock(&pop_mutex);
printf("Enter the value to push: ");
scanf("%d",&n);
top++;
stack[top]=n;
pthread_mutex_unlock(&pop_mutex);
pthread_mutex_unlock(&push_mutex);
printf("Value is pushed to stack \n");
}

void * pop(void *arg) {
int k;
pthread_mutex_lock(&push_mutex);
sleep(5);
pthread_mutex_lock(&pop_mutex);
k=stack[top];
top--;
printf("Value popped from stack is %d \n",k);
pthread_mutex_unlock(&pop_mutex);
pthread_mutex_unlock(&push_mutex);
}

int main() {
pthread_t tid1,tid2;
pthread_create(&tid1,NULL,&push,NULL);
pthread_create(&tid2,NULL,&pop,NULL);
printf("Both threads are created\n");
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
return 0;
}

Now, let's go behind the scenes.