线程同步 -mutex

线程同步 - 1

互斥量

为什么要使用互斥量

当多个线程共享相同的内存时,需要每一个线程看到相同的视图。当一个线程修改变里时,而其他线程也可以读取或者修改这个变里,就需爰对这些线程同步,确保他们不会访问到无效的变量。

在变里候改时间多于一个存储器访问周期的处理器结构中,当存储器的读和写这两个周期交叉时,这种潜在的不一致性就会出现·当然这与处理器相关,但是在可移植的程序中并不能对处理器做出任何假设。

相关例子

两个线程同时修改一个变量

代码

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

struct student{
    
    
    int id;
    int age;
    int name;
} stu;

int i=1;

void *thread_func1(void *arg){
    
    
    while(1){
    
    
        stu.id = i;
        stu.age = i;
        stu.name = i;
        i++;
        
        if(stu.id != stu.age || stu.id != stu.name || stu.age != stu.name){
    
    
            printf("I am thread 1 : %d, %d, %d \n", stu.id, stu.age, stu.name);
            break;
        }
    }
    return (void *)0;
}

void *thread_func2(void *arg){
    
    
    while(1){
    
    
        stu.id = i;
        stu.age = i;
        stu.name = i;
        i++;
        
        if(stu.id != stu.age || stu.id != stu.name || stu.age != stu.name){
    
    
            printf("I am thread 2 : %d, %d, %d \n", stu.id, stu.age, stu.name);
            break;
        }
    }
    return (void *)0;
}

int main(){
    
    
    
    pthread_t tid1, tid2;
    int err;
    
    err = pthread_create(&tid1, NULL, thread_func1, NULL);
    if(err){
    
    
        printf("new thread 1 create failed \n");
        return ;
    }
    
    err = pthread_create(&tid2, NULL, thread_func2, NULL);
    if(err){
    
    
        printf("new thread 2 create failed \n");
        return ;
    }
    
    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);
    
    return 0;
}


运行结果

carey@ubuntu:~/thread$ ./thread_mutex 
I am func 2: 24342 24342 24341 
^C

互斥量使用

为了让线程访问数据不产生冲突,这要就需要对变里加锁,使得同一时刻只有一个线程可以访问变里。互斥量本质就是锁,访问共享资源前对互斥量加锁,访问完成后解锁。

当互斥量加锁以后,其他所有需要访问该互斥量的线程都将阻塞。

当互斥量解锁以后,所有因为这个互斥量阻塞的线程都将变为就绪态,第一个获得cpu的线程会获得互斥量,变为运行态,而其他线程会继续变为阻塞·在这种方式下访问互斥量每次只有一个线程能向前执行。

互斥量用 pthread_mutex_t 类型的数据表示,在使用之前需要对互斥量初始化。

1、如果是动态分配的互斥量,可以调用pthread_mutex_init()函数初始化。

2、如果是静态分配的互斥量,还可以把它置为常量 PTHREAD_MUTEX_INITIALIZER。

3、动态分配的互斥量在释放内存之前需要调用 pthread_mutex_destroy ( )

int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t*restrict attr);

第一个参数是要初始化的互斥量,第二个参数是互斥量的属性,默认为NULL

int pthread_mutex_destroy(pthread_mutex_t 'mutex);
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

加锁
int pthread_mutex_lock(pthread_mutex_t "mutex);
成功返回0,失败返回错误码。如果互斥里已经镞锁住,那么会导致该线程阻塞。

int pthread_mutex_trylock(pthread_mutex_t "mutex);
成功返回0,失败返回错误码。如果互斥里已经被锁住,不会导致线程阻塞。

解锁
int pthread_mutex_unlock(pthread_mutex_t "mutex);成功返回0,失败运回错误码。

代码

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

struct student{
    
    
        int id;
        int age;
        int name;
}s;

int i;

pthread_mutex_t mutex;

void *thread_func1(void *arg){
    
    

        while(1){
    
    

                pthread_mutex_lock(&mutex);

                s.id = i;
                s.age = i;
                s.name = i;
                i++;

                if(s.id != s.age || s.id != s.name || s.age != s.name){
    
    

                        printf("I am func 1: %d %d %d \n", s.id, s.age, s.name);
                        break;

                }

                pthread_mutex_unlock(&mutex);

        }
        return (void *)0;

}

void *thread_func2(void *arg){
    
    

        while(1){
    
    

                pthread_mutex_lock(&mutex);

                s.id = i;
                s.age = i;
                s.name = i;
                i++;

                if(s.id != s.age || s.id != s.name || s.age != s.name){
    
    

                        printf("I am func 2: %d %d %d \n", s.id, s.age, s.name);
                        break;

                }

                pthread_mutex_unlock(&mutex);

        }
        return (void *)0;

}


int main(){
    
    


        pthread_t tid1, tid2;
        int err;

        err = pthread_mutex_init(&mutex, NULL);
        if(err){
    
    

                printf("init mutexfailed \n");
                return ;

        }

        err = pthread_create(&tid1, NULL, thread_func1, NULL);
        if(err){
    
    

                printf("new thread 1 create failed \n");
                return ;

        }

        err = pthread_create(&tid2, NULL, thread_func2, NULL);
        if(err){
    
    

                printf("new thread 2 create failed \n");
                return ;

        }

        pthread_join(tid1, NULL);
        pthread_join(tid2, NULL);


        return 0;
}


解析

加锁之后由于变量不会再回被多个线程调用,所以不会出现错乱。

猜你喜欢

转载自blog.csdn.net/qq_44861043/article/details/119608996
今日推荐