精华内容
下载资源
问答
  • 互斥锁作用的理解

    万次阅读 多人点赞 2018-08-13 00:47:30
    在学习线程控制的时候,接触到了互斥锁这个概念,下面讲讲我了解到的互斥锁作用 互斥锁的创建 1.pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER; 2.pthread_mutex_t mutex; pthread_mutex_init(&...

    在学习线程控制的时候,接触到了互斥锁这个概念,下面讲讲我了解到的互斥锁的作用

    互斥锁的创建

    1.pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
    2.pthread_mutex_t mutex;
    pthread_mutex_init(&mutex);
    以上两种方式都行

    互斥锁在一个线程中的使用

    pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;//创建互斥锁并初始化
    
    pthread_mutex_lock(&mutex);//对线程上锁,此时其他线程阻塞等待该线程释放锁
    
    ----
    要执行的代码段
    ----
    
    pthread_mutex_unlock(&mutex);//执行完后释放锁
    

    那么为什么要将要执行的的代码加锁后再执行呢

    先了解一下原子操作的概念

    所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程)
    原子操作是不可分割的,在执行完毕之前不会被任何其它任务或事件中断
    ——百度百科
    意思就是这种操作是单位级的操作,执行过程绝对不受影响,执行结果一定

    假如现在有两个线程都在修改一个全局变量

    int number = 10;
    
    void p(void)
    {
        number*=2;
        printf("%d\n",number);
    }
    void q(void)
    {
        number+=1;
        printf("%d\n",number);
    }
    
    int main(void)
    {
        pthread_t tid1,tid2;
        pthread_create(&tid1,NULL,(void*)(&p),NULL);
        pthread_create(&tid2,NULL,(void*)(&q),NULL);
        pthread_join(tid1);
        pthread_join(tid2);
    
    }

    执行上面这段程序,最后number的值是多少?你可能会说如果先加,那么最终结果就是22,否则就是21。真的是这样吗?其实并不是的

    上图为执行+=操作的步骤,方框为寄存器,在加一时,先从变量空间拿出变量值,然后在寄存器中加一,最后将加一的值放回变量空间将原值覆盖,从而完成一次加操作。

    这里写图片描述

    上图表示了两个线程对全局变量操作的一种情况,线程1和2都拿到number的初始值,线程1操作后将11放回变量空间,但是线程2不久后将20也放回变量空间将11覆盖。

    所以互斥锁就是为了避免这种情况,在一个线程修改变量时加锁,则其他变量阻塞,等待加锁的变量解锁后再执行,这样避免了如图的情况和其他的异常情况。
    以上就是我对学到的互斥锁作用的理解,如有错误欢迎指正

    展开全文
  • 互斥锁

    2019-10-23 10:59:17
    1、互斥锁基本原理: 互斥锁是一个二元变量,其状态为开锁(允许0)和上锁(禁止1),将某个共享资源与某个特定互斥锁在逻辑上绑定(要申请该资源必须先获取锁)。 (1)访问公共资源前,必须申请该互斥锁,若处于开锁状态...

    互斥锁

    线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制是引入互斥锁。互斥锁为资源引入一个状态:锁定/非锁定。某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性

    1、互斥锁基本原理:
    互斥锁是一个二元变量,其状态为开锁(允许0)和上锁(禁止1),将某个共享资源与某个特定互斥锁在逻辑上绑定(要申请该资源必须先获取锁)。
    (1)访问公共资源前,必须申请该互斥锁,若处于开锁状态,则申请到锁对象,并立即占有该锁,以防止其他线程访问该资源;如果该互斥锁处于锁定状态,则阻塞当前线程。
    (2)只有锁定该互斥锁的进程才能释放该互斥锁,其他线程试图释放无效。

    2、初始化互斥锁:
    使用之前,需要定义互斥锁,使用函数:pthread_mutex_t lock;进行定义

    extern int    pthread_mutex_init(pthread_mutex_t * **_mutex**,_const pthread_mutex_mutexattr_t*  **_mutexattr**)
    

    参数: _mutex 初始化的互斥锁的指针
    _mutexattr 指向对象的指针,若为空则默认属性

    3、申请互斥锁
    如果一个线程要占用共享资源,必须先申请对应互斥锁,使用函数:
    以阻塞方式申请互斥锁:

    extern int pthread_mutex_lock(pthread_mutex* _mutex)
    

    以非阻塞方式申请互斥锁:

    extern int pthread_mutex_trylock(pthread_mutex* _mutex
    

    4、释放互斥锁
    释放互斥锁函数:

    extern int pthread_mutex_unlock(pthread_mutex_t* _mutex)
    

    死锁

    死锁是指一个资源被多次调用,而多次调用方都未能释放该资源就会造成一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁

    死锁产生:
    一个线程内部多次加锁缺没有释放引起死锁
    多个线程内部多次调用引起死锁
    python中的实例

    展开全文
  • Linux互斥锁及其应用

    千次阅读 2020-07-27 21:34:02
    文章目录互斥锁1.1锁的创建1.2 锁操作1.3 锁销毁1.4互斥锁属性初始化互斥锁属性对象pthread_mutexattr_init 语法pthread_mutexattr_init 返回值销毁互斥锁属性对象pthread_mutexattr_destroy 语法pthread_mutexattr_...

    互斥锁

    作用: 防止多线程对同一个数据同时进行操作

    在线程实际运行过程中,我们经常需要多个线程保持同步。这时可以用互斥锁来
    完成任务。

    1.1锁的创建

    互斥锁可以动态或静态的被创建
    可以用宏PTHREAD_MUTEX_INITIALIZER来静态的初始化锁,采用这种方式比较容易理解

    互斥锁是pthread_mutex_t的结构体,而这个宏是一个结构常量,如下可以完成静态的初始化锁:

    pthread_mutex_t mutex =PTHREAD_MUTEX_INITIALIZER;
    

    动态创建是通过pthread_mutex_init函数实现,函数原型如下:

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

    其中:

    1. mutex:所需创建的锁;
    2. attr:创建锁的属性。一般默认为NULL,
      分为以下几个属性:
      PTHREAD_MUTEX_TIMED_NP这是缺省值,也就是普通锁。当一个线程加锁以后,其余请求锁的线程将形成一个等待队列,并在解锁后按优先级获得锁。这种锁策略保证了资源分配的公平性;
      PTHREAD_MUTEX_RECURSIVE_NP嵌套锁,允许同一个线程对同一个锁成功获得多次,并通过多次unlock解锁。如果是不同线程请求,则在加锁线程解锁时重新竞争;
      PTHREAD_MUTEX_ERRORCHECK_NP检错锁,如果同一个线程请求同一个锁,则返回EDEADLK,否则与PTHREAD_MUTEX_TIMED_NP类型动作相同。这样就保证当不允许多次加锁时不会出现最简单情况下的死锁;
      PTHREAD_MUTEX_ADAPTIVE_NP适应锁,动作最简单的锁类型,仅等待解锁后重新竞争;

    1.2 锁操作

    对锁的操作主要包括加锁pthread_mutex_lock()解锁pthread_mutex_unlock()
    测试加锁pthread_mutex_trylock()三个,函数原型如下:

    int pthread_mutex_lock(pthread_mutex_t*mutex); 
    int pthread_mutex_unlock(pthread_mutex_t *mutex); 
    int pthread_mutex_trylock(pthread_mutex_t *mutex); 
    

    pthread_mutex_trylock()语义与pthread_mutex_lock()类似,不同的是在锁已经被占据时返回EBUSY而不是挂起等待

    1.3 锁销毁

    创建的互斥锁在不使用的时候需要消耗,不然会造成系统资源的流失,其函数原
    型如下:

    int pthread_mutexattr_destroy(pthread_mutex_t *mutex);
    

    1.4互斥锁属性

    使用互斥锁(互斥)可以使线程按顺序执行。通常,互斥锁通过确保一次只有一个线程执行代码的临界段来同步多个线程。互斥锁还可以保护单线程代码。
    要更改缺省的互斥锁属性,可以对属性对象进行声明和初始化。通常,互斥锁属性会设置在应用程序开头的某个位置,以便可以快速查找和轻松修改。

    初始化互斥锁属性对象

    使用pthread_mutexattr_init(3C)可以将与互斥锁对象相关联的属性初始化为其缺省值。在执行过程中,线程系统会为每个属性对象分配存储空间。

    pthread_mutexattr_init 语法

    int pthread_mutexattr_init(pthread_mutexattr_t *mattr); 
    
    #include <pthread.h> 
    pthread_mutexattr_t mattr; 
    int ret;/* initialize an attribute to default value */ 
    ret = pthread_mutexattr_init(&mattr);
    

    调用此函数时,pthread 属性的缺省值为 PTHREAD_PROCESS_PRIVATE。 该值表示可以在进程内使用经过初始化的互斥锁。

    mattr 的类型为 opaque,其中包含一个由系统分配的属性对象。mattr 范围可能的值为 PTHREAD_PROCESS_PRIVATE 和 PTHREAD_PROCESS_SHARED。 PTHREAD_PROCESS_PRIVATE 是缺省值。
    对于互斥锁属性对象,必须首先通过调用 pthread_mutexattr_destroy(3C) 将其销毁,才能重新初始化该对象。pthread_mutexattr_init() 调用会导致分配类型为 opaque 的对象。如果未销毁该对象,则会导致内存泄漏。

    pthread_mutexattr_init 返回值

    pthread_mutexattr_init() 成功完成之后会返回零。其他任何返回值都表示出现了错误。如果出现以下情况,该函数将失败并返回对应的值。

    ENOMEM 描述:内存不足,无法初始化互斥锁属性对象。

    销毁互斥锁属性对象

    pthread_mutexattr_destroy(3C)可用来取消分配用于维护
    pthread_mutexattr_init() 所创建的属性对象的存储空间。

    pthread_mutexattr_destroy 语法

    
    int pthread_mutexattr_destroy(pthread_mutexattr_t *mattr) 
    
    #include <pthread.h> 
    pthread_mutexattr_t mattr; 
    int ret;/* destroy an attribute */ ret = pthread_mutexattr_destroy(&mattr); 
    

    pthread_mutexattr_destroy 返回值

    pthread_mutexattr_destroy() 成功完成之后会返回零。其他任何返回值都表示出现了错误。如果出现以下情况,该函数将失败并返回对应的值。

    EINVAL 描述: 由 mattr 指定的值无效。

    案例

    /*************************************************************************
        > File Name: pthread.c
        > Author: 杨永利
        > Mail: 1795018360@qq.com 
        > Created Time: 2020年07月27日 星期一 20时42分45秒
     ************************************************************************/
    
    #include <stdio.h>
    #include <pthread.h>
    
    void * thread_addi(void *arg)
    {
        int* tmp=arg;
        int i=0;
        for(i;i<1000000;i++)
        {
            ++(*tmp);
            //printf("%d\n",i);
        }
    
        return NULL;
    }
    
    int main(int argc, char* argv[]){
        int i=0;
        printf("我的初始化i是:%d\n",i);
        long int s=(long int)&i;
        pthread_t pid;
        pthread_create(&pid,NULL,thread_addi,&i);
        int j=0;
        for(j;j<1000000;j++)
        {
            i++;
            //printf("%d\n",i);
        }
        void *v;
        pthread_join(pid,v);
        printf("%s\n",(char*)v);
        printf("i最终的值为:%d\n",i);
        
        return 0;
    }
    
    

    遇到问题

    运行之后我们会发现i的最终结果里2000000差很多,这是为什么呢???

    这是因为两个线程的时间片分配时产生了干扰,当数特别小时干扰是看不到的,但是当进行的操作增大时,系统在给两个线程分配时间片时就会产生干扰,也就是上个例子中和最终加不满的问题。

    那么 我们就在加数操作之后来加一句输出延缓时间,看看能不能加到2000000,
    在这里插入图片描述
    我们可以看到这已经很接近2000000了,但是还是无法加到最后

    那么怎样改进呢?这就用到了我们的互斥锁。

    解决方案

    在加数操作上加上加锁和解锁操作。

    1.在循环外加锁解锁

    在这里插入图片描述

    结果在这里插入图片描述

    2.在循环内加锁解锁(效率最高)

    /*************************************************************************
        > File Name: pthread.c
        > Author: 杨永利
        > Mail: 1795018360@qq.com 
        > Created Time: 2020年07月27日 星期一 20时42分45秒
     ************************************************************************/
    
    #include <stdio.h>
    #include <pthread.h>
    
    pthread_mutex_t mutex;
    
    void * thread_addi(void *arg)
    {
        int* tmp=arg;
        int i=0;
        for(i;i<1000000;i++)
        {
            pthread_mutex_lock(&mutex);
            ++(*tmp);
            //printf("%d\n",i);
            pthread_mutex_unlock(&mutex);
        }
    
        return NULL;
    }
    
    int main(int argc, char* argv[]){
        int i=0;
        printf("我的初始化i是:%d\n",i);
        long int s=(long int)&i;
        int err=pthread_mutex_init(&mutex,NULL);
        if(err!=0)
        {
            printf("锁创建失败\n");
            return -1;
        }
    
        pthread_t pid;
        pthread_create(&pid,NULL,thread_addi,&i);
        int j=0;
        for(j;j<1000000;j++)
        {
            pthread_mutex_lock(&mutex);
            i++;
            //printf("%d\n",i);
            pthread_mutex_unlock(&mutex);
        }
        void *v;
        pthread_join(pid,v);
        printf("%s\n",(char*)v);
        printf("i最终的值为:%d\n",i);
        
        return 0;
    }
    
    
    展开全文
  • GIL锁与互斥锁

    2018-09-08 03:37:15
    Global Interpreter Lock 全局解释器锁 由于Cpython解释器在运行python文件时,Cpython进程与其运行文件所产生的主进程是一个进程(文件进程相当于Cpython的一个线程...互斥锁作用: 互斥锁用于python文件运行进程...

    Global Interpreter Lock 全局解释器锁
    由于Cpython解释器在运行python文件时,Cpython进程与其运行文件所产生的主进程是一个进程(文件进程相当于Cpython的一个线程),Cpython的GIL锁就产生了(Cpython的一个线程)当python文件中的线程想要执行其代码,必须获得GIL权限,否则不能执行

    互斥锁作用:
    互斥锁用于python文件运行进程(线程)时,使数据修改等操作的竞争变得有序化

    程序运行分析
    1、运行一个python进程,内有两个线程Thread-1,Thread-2,共享数据num
    2、Thread-1要运行其代码改num,GIL获得,Thread-1可以改,Thread-1获得Lock
    3、Thread-1代码在改num前先执行time.sleep(I/O啥的,就是没运行到改num)
    4、这时Thread-2要运行其代码去修改num,由于Thread-1是阻塞状态,Thread-2获得GIL
    5、由于Thread-1有Lock,所以Thread-2无法更改num
    6、这时Thread-1又抢到GIL,由于其保留Lock所以其可以继续运行代码使其修改num
    7、当Thread-1执行完释放lock后,Thread-2在获得GIL与Lock后才可对num进行修改

    展开全文
  • 互斥锁作用 怎样同步多个线程和进程之间的活动,为允许在线程和进程间共享数据,同步通常是必需的,互斥锁和条件变量是同步的基本组成部分。 互斥锁和条件变量被用来同步一个进程内的各个线程,如果一个互斥锁或...
  • 1.互斥锁作用: 互斥锁mutex是用来保护线程间共享的全局变量安全的一种机制,保证多线程中在某一时刻只允许某一个线程对临界区的访问。 2.初始化方式: 互斥锁对象的数据类型是 pthread_mutex_t ; 互斥锁的初始方式...
  • Linux:多线程-互斥锁

    2019-11-28 17:50:40
    1.互斥锁作用 在Linux下,多个线程拥有同一个虚拟地址空间,若多个线程对同一块数据进行操作,可能会产生二义性。造成逻辑混乱。为了保证不发生这些,就需要线程安全。 线程安全的概念:多个线程对同一个临界资源...
  • 互斥锁:mutex,用于保证在任何时刻,都只能有一个线程访问该对象。当获取锁操作失败时,线程会进入睡眠,等待锁释放时被唤醒 读写锁:rwlock,分为读锁和写锁。处于读操作时,可以允许多个线程同时获得读操作。但是...
  • 自旋锁 互斥锁

    2015-07-18 20:53:16
    自旋锁 互斥锁本文从以下3个方面来介绍。 1. 为什么会有自旋锁、互斥锁? 2. 什么是自旋锁、互斥锁? 3. 分别有什么作用?1. 为什么会有自旋锁、互斥锁?讲这些锁之前,先谈以下并发、临界区、同步的概念。1.1...
  • 互斥锁

    2019-07-15 18:16:25
    互斥锁 互斥锁的概念: 互斥锁:对共享数据进行锁定,保证同一时刻只能有一个线程去操作。 注意:互斥锁是多个线程一起去抢,抢到锁的线程先执行,没有抢到锁的线程需要等待,等互斥锁使用完释放后,其它等待的...
  • FreeRTOS互斥锁

    千次阅读 2019-03-09 23:06:35
    信号量API函数实际上都是宏,它使用现有的队列机制。这些宏定义在semphr.h文件中。如果使用信号量或者互斥...互斥锁和递归互斥锁互斥锁是用来保证共享数据操作的完整性,同时只能有一个任务访问共享数据。递归互斥...
  • LiteOS 互斥锁

    2019-05-30 16:17:31
    参考: ...常用于实现对**临界资源的独占式处理,**任意时刻,互斥锁的状态只有两种,开锁或者闭锁,互斥锁被持有,则为闭锁状态,其他任务无法对该互斥锁进行开锁或持有,当任务释放互斥锁,该...
  • 线程互斥锁作用: 线程互斥锁通过锁机制来实现线程间的同步。在同一时刻,线程互斥锁只允许一个线程执行一个关键部分的代码。 线程互斥锁用法: 1) 操作互斥锁的函数: pthread_mutex_init () //初始化一个互斥锁 ...
  • POSIX 互斥锁&属性块

    2021-04-23 13:43:07
    互斥锁属性块 1.互斥锁属性块的初始化和删除 2.设置和获取互斥锁属性块的类型 3.设置和获取互斥锁属性块的算法类型 4.设置和获取互斥锁属性块的天花板优先级 5.设置和获取互斥锁属性块的进程共享属性 ...
  • 互斥锁属性

    2018-01-11 13:34:53
    使用互斥锁(互斥)可以使线程按顺序执行。通常,互斥锁通过确保一次只有一个线程执行代码的临界段来同步多个线程。互斥锁还可以保护单线程代码。 要更改缺省的互斥锁属性,可以对属性对象进行声明和初始化。通常...
  • 1.1 互斥锁作用 在编程中,对象互斥锁用来保证共享数据操作的完整性。每个对象都对应于一个可称为"互斥锁" 的标记,这个标记用来保证在某个时刻,只能有一个线程访问该对象。 1.2 互斥锁介绍 互斥锁是使用加锁的...
  • python之互斥锁

    2021-03-19 19:25:16
    python之互斥锁 1.互斥锁的概念 互斥锁: 对共享数据进行锁定,保证同一时刻只能有一个线程去操作。 【对共享数据进行锁定可以理解为全局变量】 注意: 互斥锁是多个线程一起去抢,抢到锁的线程先执行,没有抢到锁...
  • MySQL:共享锁 互斥锁 意向锁。

    千次阅读 2019-12-16 14:01:43
    MySQL:共享锁 互斥锁 意向锁。
  • 线程之互斥锁与死锁

    万次阅读 2017-06-05 14:00:31
    互斥锁: 1、互斥锁基本原理: 互斥锁是一个二元变量,其状态为开锁(允许0)和上锁(禁止1),将某个共享资源与某个特定互斥锁在逻辑上绑定(要申请该资源必须先获取锁)。 (1)访问公共资源前,必须申请该互斥锁,若...
  • python 互斥锁

    2019-01-18 09:05:18
    一、互斥锁作用: 保证多线程下数据的正确性—某个线程要共享数据时,先将其锁定,此时资源的状态为“锁定”, 其他线程不能更改;直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源...
  • 自旋锁和互斥锁

    2018-06-14 23:11:28
    自旋锁(Spin lock)自旋锁与互斥锁有点类似,只是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是 否该自旋锁的保持者已经释放了锁,"自旋"一词就是因此而得名。...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 73,127
精华内容 29,250
关键字:

互斥锁的作用