线程同步 -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;
}


解析

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值