Mutex and deadlock

Posted by 555sandy on Fri, 08 Oct 2021 03:23:20 +0200

Function and operation of mutex

mutex
Mutex is a solution to the conflict caused by multiple threads operating on shared resources at the same time when multiple threads access shared resources. When executing, which thread holds the mutex and locks the shared resources before operating on shared resources. At this time, other threads cannot operate on shared resources. Only after the thread holding the lock unlocks and releases the lock can other threads rob and lock.
Its main function is to solve the problem of multi-threaded competition for shared resources.

pthread_mutex_init mutex initialization

Prototype:
  int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);
  
Parameters:
Mutex: mutex variable address (mutex resource)
attr: attribute information
  
return:
Success: 1
Failed: errorr (error number)

pthread_mutex_lock lock

Prototype:
  int pthread_mutex_lock(pthread_mutex_t *mutex);
  
Parameters:
Mutex: mutex variable address (mutex resource)

return:
Success: 1
Failed: errorr (error number)

pthread_mutex_unlock unlock

Prototype:
  int pthread_mutex_unlock(pthread_mutex_t *mutex);
  
Parameters:
Mutex: mutex variable address (mutex resource)
  
return:
Success: 1
Failed: errorr (error number)

pthread_mutex_destroy destroy mutex

Prototype:
  int pthread_mutex_unlock(pthread_mutex_t *mutex);
  
Parameters:
Mutex: mutex variable address (mutex resource)
  
return:
Success: 1
Failed: errorr (error number)

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

pthread_mutex_t  mutex;     //Define a lock resource variable (parameter transfer is prone to problems) 

void *func(void *arg);
 
int main(int argc, char **argv)
{
    int status = pthread_mutex_init(&mutex,NULL);   //Initialize mutex

    pthread_t thread;
    pthread_create (&thread, NULL,func,NULL);//Create thread

    while(1)       //Cyclic locking
    {
        int i = 0;
        pthread_mutex_lock(&mutex);//Lock
        printf("11111 I locked it\n");  
        while(1)
        {
            i++; 
            if(i == 200)
            {

                printf("i = %d\n",i);
                printf("11111 I unlocked it\n");  

                pthread_mutex_unlock(&mutex);   //Unlock
                break;   
            }
        }
        sleep(1); //Prevent locking immediately after unlocking 

      
    }

    return 0;
}


void *func(void *arg)
{
    pthread_t id = pthread_self();  //Get current thread id
	pthread_detach(id);     //Set self separation
	
    while(1)       //Cyclic locking
    {
        int k = 0;
        pthread_mutex_lock(&mutex);//Lock
        printf("22222 I locked it\n");  
        while(1)
        {
            k++; 
            if(k == 200)
            {
                printf("k = %d\n",k);
                printf("22222 I unlocked it\n");  

                pthread_mutex_unlock(&mutex);   //Unlock
                break;
                    
            }
        }
        sleep(1);   
      
    }
} 

deadlock

Causes of deadlock
Deadlocks can occur when a process needs exclusive access to resources. Deadlock is a deadlock caused by two or more processes competing for critical resources, that is, a process waits for a resource that has been occupied and will never be released. Without external forces, these processes cannot move forward.

Four conditions for deadlock generation

mutual exclusion
The resources involved are not shared, that is, only one process can use them at a time. If another process requests the resource, the requesting process must wait until the resource is released.

Conditions of non deprivation (non preemption)
The resources obtained by a process cannot be forcibly taken away by other processes before they are used up, that is, they can only be released by the process that obtains the resources.

Occupy and wait (partial distribution)
A process requests a portion of its resources at a time. While waiting for a new resource, the process continues to occupy the allocated resources.

Loop condition (cycle wait)
There is a circular chain with process endings. Each process in the chain is waiting for the resources held by the next process, resulting in this group of processes in a permanent waiting state.

These four conditions are necessary for deadlock. As long as the system deadlock occurs, these conditions must be true. Conversely, as long as one of the above conditions is not satisfied, deadlock will not occur. Therefore, to avoid deadlock, you only need to break its necessary conditions.

Deadlock prevention in threads

pthread_cleanup_push stack thread processing function

Prototype:
  void pthread_cleanup_push(void (*routine)(void *), void *arg)
  
function
Function stack (thread cleanup function)
  
Parameters:
routine: canceling function of thread
arg: parameter of the thread's cancel handler

pthread_cleanup_pop stack pressing thread processing function

Prototype:
  void pthread_cleanup_pop(int execute)
  
function
This function calls pthread when the program terminates abnormally_ cleanup_ Push() is pushed into the cleaning function stack, which is managed by the first in then out stack structure
  
Parameters:
  execute:
Write 0: cancel the stack thread processing function, but do not execute the function
Non 0: cancel the processing function of the pop-up stack thread and execute the function
This parameter does not affect the execution of the cleanup function upon abnormal termination

Sample code


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

//Define mutex
pthread_mutex_t  mutex;

void *routine(void *arg);

void function(void *arg);

int main()
{

	pthread_mutex_init(&mutex, NULL);//Initialize mutex
		
	pthread_t id;//Define a thread ID number
	pthread_create(&id, NULL, routine, NULL);//Create thread -- save address of thread id number
	
	while(1)    //Cyclic locking
	{
		pthread_mutex_lock(&mutex); //Lock
        printf("1 I locked it!!\n");

        char buf[128];
		while(1)
        {
            printf("Thread 1:");
            scanf("%s", buf);
            if(!strcmp(buf,"A"))
            {
                break;
            }

        }

        printf("1 I unlocked!!\n");
		pthread_mutex_unlock(&mutex);//Unlock
        sleep(1);
	}
	
	pthread_mutex_destroy(&mutex);//Destroy mutex

	pthread_exit(NULL);
}

//Thread function
void *routine(void *arg)
{
    
	pthread_t id = pthread_self();

	while(1)
	{
		
		pthread_mutex_lock(&mutex);//Lock
        pthread_cleanup_push(function,NULL);    //Function stack (thread cleanup function)

        printf("2 I locked it!!\n");

        char buf[128];
		while(1)
        {
            printf("Thread 2:");
            scanf("%s", buf);
            if(!strcmp(buf,"B"))
            {
                break;
            }
            if(!strcmp(buf,"Z"))
            {
                pthread_cancel(id);     //Cancel thread
            }
        }

        printf("2 I unlocked!!\n");
        pthread_mutex_unlock(&mutex); //Unlock
        pthread_cleanup_pop(0);     //Normal exit does not execute thread cleanup function

        sleep(1);
	}

	return NULL;
}

//Cleanup function (deadlock prevention)
void function(void *arg)
{
    printf("Yo, what's the matter\n");

    //Unlock (prevent deadlock caused by abnormal thread termination)
    pthread_mutex_unlock(&mutex);

}

Topics: C