Linux–Threads–Mutex lock

1. Mutex
a) A mutex is essentially a lock. Generally, defining a mutex in the main thread means defining a lock. Then operate this lock on the thread according to our needs.

b) If all threads are locked, the threads will fight for memory space. Whoever gets it first will run first. Until the thread is unlocked, other threads can only wait and block.

c) Because the main thread is not locked, when the thread that gets the lock first is running, the main thread will also run.

include //Return: Return 0 if successful, otherwise return error number
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);Create lock
int pthread_mutex_lock(pthread_mutex_t *mutex);//Lock
int pthread_mutex_unlock(pthread_mutex_t *mutex);//unlock
int pthread_mutex_destroy(pthread_mutex_t *mutex);//Destroy the lock

Mutexes are represented by the pthread_mutex_t data type. A mutex must be initialized before using it. You can initialize it by calling the pthread_mutex_init function. If the mutex is allocated dynamically (for example, by calling the malloc function), then pthread_mutex_destroy. needs to be called before freeing the memory.

To initialize a mutex with default attributes, simply set attr to NULL.

Lock: If a thread does not want to be blocked, it can use pthread_mutex_trylock to try to lock the mutex. If the mutex is in an unlocked state when pthread_mutex_trylock is called, then pthread_mutex_trylock will lock the mutex without blocking and return 0. Otherwise, pthread_mutex_trylock will fail and cannot lock the mutex and return EBUSY.

2. Simple operation to lock and unlock:

Code:

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

int data = 0; //Define a global variable data
pthread_mutex_t mutex;//Create a lock
void *func1(void *arg)
{
        int i;
        pthread_mutex_lock( & amp;mutex);//Lock

        for(i=0;i<5;i + + ){
                printf("t1:thread id is:%ld\
",(unsigned long)pthread_self());
                printf("t1:is param:%d\
",*((int *)arg));
                sleep(1);
        }

        pthread_mutex_unlock( & amp;mutex);//Unlock
}
void *func2(void *arg)
{
        pthread_mutex_lock( & amp;mutex);//Lock

        printf("t2:thread id is:%ld\
",(unsigned long)pthread_self());
        printf("t2:is param:%d\
",*((int *)arg));

        pthread_mutex_unlock( & amp;mutex);//Unlock

}
void *func3(void *arg)
{
        pthread_mutex_lock( & amp;mutex);//Lock

        printf("t3:thread id is:%ld\
",(unsigned long)pthread_self());
        printf("t3:is param:%d\
",*((int *)arg));

        pthread_mutex_unlock( & amp;mutex);//Unlock

}
int main()
{
        int ret;
        int param = 100;
        pthread_t t1;
        pthread_t t2;
        pthread_t t3;

        pthread_mutex_init( & amp;mutex,NULL);//Initialize lock

        ret = pthread_create( & amp;t1,NULL,func1,(void *) & amp;param);//Create thread t1
        if(ret==0){
                printf("main: Thread t1 was created successfully!\
");
        }

        ret = pthread_create( & amp;t2,NULL,func2,(void *) & amp;param);//Create thread t2
        if(ret==0){
                printf("main: Thread t2 was created successfully!\
");
        }

        ret = pthread_create( & amp;t3,NULL,func3,(void *) & amp;param);//Create thread t3
        if(ret==0){
                printf("main: Thread t3 was created successfully!\
");
        }
        printf("main: Get the ID of the main program: %ld\
", (unsigned long)pthread_self());


        pthread_join(t1,NULL);
        pthread_join(t2,NULL);
        pthread_join(t3,NULL);

        return 0;
}

result:

The t1 thread that gets the lock first runs first, but it will compete with the main thread for memory because the main thread is not locked. Although it will be interrupted, for other t2 and t3 threads, they can only wait and block, waiting for t1 to run first. over

3. Mutex lock restricts access to shared memory

#include<stdio.h>
#include<pthread.h>
#include <unistd.h>
#include<stdlib.h>
int data = 0; //Define a global variable data
pthread_mutex_t mutex;

void *func1(void *arg)
{

        pthread_mutex_lock( & amp;mutex);
        while(1){
                printf("Thread t1 got data = %d\
",data + + );
                sleep(1);
                if(data == 5){
                   printf("t1:data = %d\
",data);
                   pthread_mutex_unlock( & amp;mutex);
                   printf("=========t1 thread exit============\
");
                   exit(0);
                }
        }

}
void *func2(void *arg)
{

        while(1){
                printf("Thread t2 got data = %d\
",data);
                pthread_mutex_lock( & amp;mutex);
                data + + ;
                pthread_mutex_unlock( & amp;mutex);
                sleep(1);
        }
}
int main()
{
        int ret;
        int param = 100;
        pthread_t t1;
        pthread_t t2;

        pthread_mutex_init( & amp;mutex,NULL);
        ret = pthread_create( & amp;t1,NULL,func1,(void *) & amp;param);//Create thread t1
        if(ret==0){
                printf("main: Thread t1 was created successfully!\
");
        }

        ret = pthread_create( & amp;t2,NULL,func2,(void *) & amp;param);//Create thread t2
        if(ret==0){
                printf("main: Thread t2 was created successfully!\
");
        }


        printf("Main thread main gets data:%d\
",data);
        pthread_join(t1,NULL);
        pthread_join(t2,NULL);

        pthread_mutex_destroy( & amp;mutex);
        
        return 0;
}

result:

After t2 is unlocked, t1 keeps holding the lock until the loop ends and the entire program exits because it is a shared memory.

4. Deadlock

The prerequisite is that two locks are defined, one thread gets the first lock and the second lock, and the other thread gets the second lock and the first lock, and then they all compete for the right to use the lock. , because they all know the first position they each have, so they have been stuck in fighting for the right to use the lock.

Code:

#include <stdio.h>
#include <pthread.h>
 
//int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
pthread_mutex_t mutex;
pthread_mutex_t mutex2;
 
int g_data=0;
 
void *func1(void *arg)
{
int i;
pthread_mutex_lock( & amp;mutex);
sleep(1);
pthread_mutex_lock( & amp;mutex2);
 
for(i=0;i<5;i + + ){
printf("t1:%ld thread is create\
",(unsigned long)pthread_self());
printf("t1:param is %d\
",*((int*)arg));
sleep(1);
}
 
pthread_mutex_unlock( & amp;mutex);
}
void *func2(void *arg)
{
        pthread_mutex_lock( & amp;mutex2);
sleep(1);
        pthread_mutex_lock( & amp;mutex);
 
        printf("t2:%ld thread is create\
",(unsigned long)pthread_self());
        printf("t2:param is %d\
",*((int*)arg));
 
        pthread_mutex_unlock( & amp;mutex);
 
}
 
 
int main()
{
int ret;
int param=100;
pthread_t t1;
pthread_t t2;
\t
pthread_mutex_init( & amp;mutex,NULL);
pthread_mutex_init( & amp;mutex2,NULL);
 
ret=pthread_create( & amp;t1,NULL,func1,(void*) & amp;param);
if(ret==0){
printf("main:create t1 success\
");
}
        ret=pthread_create( & amp;t2,NULL,func2,(void*) & amp;param);
        if(ret==0){
                printf("main:create t2 success\
");
        }
 
\t
printf("main %ld \
",(unsigned long)pthread_self());
 
pthread_join(t1,NULL);
pthread_join(t2,NULL);
 
pthread_mutex_destroy( & amp;mutex);
pthread_mutex_destroy( & amp;mutex2);
 
return 0;
}

result:

main:create t1 success
main:create t2 success
main 139666438145792
^C
CLC@Embed_Learn:~/thread$ ./a.out
main:create t1 success
main:create t2 success
main 139839917381376
^C
CLC@Embed_Learn:~/thread$ ./a.out
main:create t1 success
main:create t2 success
main 139912974800640
^C
CLC@Embed_Learn:~/thread$ 

If there is only one lock, no deadlock will occur.

Here func1 holds the lock mutex and needs to lock mutex2; func2 holds the lock mutex2 and needs to lock mutex; thus causing a deadlock.

The knowledge points of the article match the official knowledge files, and you can further learn related knowledge. C Skill Tree Home Page Overview 193968 people are learning the system