互斥锁 订阅
在编程中,引入了对象互斥锁的概念,来保证共享数据操作的完整性。每个对象都对应于一个可称为" 互斥锁" 的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。 展开全文
在编程中,引入了对象互斥锁的概念,来保证共享数据操作的完整性。每个对象都对应于一个可称为" 互斥锁" 的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。
信息
领    域
汇编语言
中文名
互斥锁
互斥锁示例
下面举例:在Posix Thread中定义有一套专门用于线程同步的mutex函数。1. 创建和销毁有两种方法创建互斥锁,静态方式和动态方式。POSIX定义了一个宏PTHREAD_MUTEX_INITIALIZER来静态初始化互斥锁,方法如下: pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER; 在LinuxThreads实现中,pthread_mutex_t是一个结构,而PTHREAD_MUTEX_INITIALIZER则是一个结构常量。动态方式是采用pthread_mutex_init()函数来初始化互斥锁,API定义如下: int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr) 其中mutexattr用于指定互斥锁属性(见下),如果为NULL则使用缺省属性。pthread_mutex_destroy ()用于注销一个互斥锁,API定义如下: int pthread_mutex_destroy(pthread_mutex_t *mutex) 销毁一个互斥锁即意味着释放它所占用的资源,且要求锁当前处于开放状态。由于在Linux中,互斥锁并不占用任何资源,因此LinuxThreads中的 pthread_mutex_destroy()除了检查锁状态以外(锁定状态则返回EBUSY)没有其他动作。2. 互斥锁属性互斥锁的属性在创建锁的时候指定,在LinuxThreads实现中仅有一个锁类型属性,不同的锁类型在试图对一个已经被锁定的互斥锁加锁时表现不同。当前(glibc2.2.3,linuxthreads0.9)有四个值可供选择:* PTHREAD_MUTEX_TIMED_NP,这是缺省值,也就是普通锁。当一个线程加锁以后,其余请求锁的线程将形成一个等待队列,并在解锁后按优先级获得锁。这种锁策略保证了资源分配的公平性。* PTHREAD_MUTEX_RECURSIVE_NP,嵌套锁,允许同一个线程对同一个锁成功获得多次,并通过多次unlock解锁。如果是不同线程请求,则在加锁线程解锁时重新竞争。* PTHREAD_MUTEX_ERRORCHECK_NP,检错锁,如果同一个线程请求同一个锁,则返回EDEADLK,否则与PTHREAD_MUTEX_TIMED_NP类型动作相同。这样就保证当不允许多次加锁时不会出现最简单情况下的死锁。* PTHREAD_MUTEX_ADAPTIVE_NP,适应锁,动作最简单的锁类型,仅等待解锁后重新竞争。3.锁操作锁操作主要包括加锁pthread_mutex_lock()、解锁pthread_mutex_unlock()和测试加锁 pthread_mutex_trylock()三个,不论哪种类型的锁,都不可能被两个不同的线程同时得到,而必须等待解锁。对于普通锁和适应锁类型,解锁者可以是同进程内任何线程;而检错锁则必须由加锁者解锁才有效,否则返回EPERM;对于嵌套锁,文档和实现要求必须由加锁者解锁,但实验结果表明并没有这种限制,这个不同还没有得到解释。在同一进程中的线程,如果加锁后没有解锁,则任何其他线程都无法再获得锁。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而不是挂起等待。4. 其他POSIX 线程锁机制的Linux实现都不是取消点,因此,延迟取消类型的线程不会因收到取消信号而离开加锁等待。值得注意的是,如果线程在加锁后解锁前被取消,锁将永远保持锁定状态,因此如果在关键区段内有取消点存在,或者设置了异步取消类型,则必须在退出回调函数中解锁。这个锁机制同时也不是异步信号安全的,也就是说,不应该在信号处理过程中使用互斥锁,否则容易造成死锁。互斥锁属性使用互斥锁(互斥)可以使线程按顺序执行。通常,互斥锁通过确保一次只有一个线程执行代码的临界段来同步多个线程。互斥锁还可以保护单线程代码。要更改缺省的互斥锁属性,可以对属性对象进行声明和初始化。通常,互斥锁属性会设置在应用程序开头的某个位置,以便可以快速查找和轻松修改。表 4–1列出了用来处理互斥锁属性的函数。表 4–1 互斥锁属性例程表 4–2中显示了在定义互斥范围时 Solaris 线程和 POSIX 线程之间的差异。表 4–2 互斥锁范围比较
收起全文
精华内容
下载资源
问答
  • 互斥锁

    2020-04-22 23:58:25
    互斥锁是多个线程一起去抢,抢到锁的线程先执行,没有抢到锁的线程需要等待,等互斥锁使用完释放后,其它等待的线程再去抢这个锁。 为了更好的理解互斥锁,请看下面的图: 互斥锁 互斥锁的使用 threading模块中定义...

    **

    互斥锁

    **
    学习目标

    能够知道互斥锁的作用
    1.互斥锁的概念
    互斥锁: 对共享数据进行锁定,保证同一时刻只能有一个线程去操作。

    注意:

    互斥锁是多个线程一起去抢,抢到锁的线程先执行,没有抢到锁的线程需要等待,等互斥锁使用完释放后,其它等待的线程再去抢这个锁。
    为了更好的理解互斥锁,请看下面的图:

    互斥锁

    1. 互斥锁的使用
      threading模块中定义了Lock变量,这个变量本质上是一个函数,通过调用这个函数可以获取一把互斥锁。

    互斥锁使用步骤:

    创建锁

    mutex = threading.Lock()

    上锁

    mutex.acquire()

    …这里编写代码能保证同一时刻只能有一个线程去操作, 对共享数据进行锁定…

    释放锁

    mutex.release()
    注意点:

    acquire和release方法之间的代码同一时刻只能有一个线程去操作
    如果在调用acquire方法的时候 其他线程已经使用了这个互斥锁,那么此时acquire方法会堵塞,直到这个互斥锁释放后才能再次上锁。
    4. 使用互斥锁完成2个线程对同一个全局变量各加100万次的操作
    import threading

    定义全局变量

    g_num = 0

    创建全局互斥锁

    lock = threading.Lock()

    循环一次给全局变量加1

    def sum_num1():
    # 上锁
    lock.acquire()
    for i in range(1000000):
    global g_num
    g_num += 1

    print("sum1:", g_num)
    # 释放锁
    lock.release()
    

    循环一次给全局变量加1

    def sum_num2():
    # 上锁
    lock.acquire()
    for i in range(1000000):
    global g_num
    g_num += 1
    print(“sum2:”, g_num)
    # 释放锁
    lock.release()

    if name == ‘main’:
    # 创建两个线程
    first_thread = threading.Thread(target=sum_num1)
    second_thread = threading.Thread(target=sum_num2)
    # 启动线程
    first_thread.start()
    second_thread.start()

    # 提示:加上互斥锁,那个线程抢到这个锁我们决定不了,那线程抢到锁那个线程先执行,没有抢到的线程需要等待
    # 加上互斥锁多任务瞬间变成单任务,性能会下降,也就是说同一时刻只能有一个线程去执行
    

    执行结果:

    sum1: 1000000
    sum2: 2000000
    说明:

    通过执行结果可以地址互斥锁能够保证多个线程访问共享数据不会出现数据错误问题

    1. 小结
      互斥锁的作用就是保证同一时刻只能有一个线程去操作共享数据,保证共享数据不会出现错误问题
      使用互斥锁的好处确保某段关键代码只能由一个线程从头到尾完整地去执行
      使用互斥锁会影响代码的执行效率,多任务改成了单任务执行
      互斥锁如果没有使用好容易出现死锁的情况
    展开全文
  • 初始化互斥锁 int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); 上锁 int pthread_mutex_lock(pthread_mutex_t *mutex); 解锁 int pthread_mutex_unlock(pthread_mutex_...

    初始化互斥锁

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

     

    上锁

    int pthread_mutex_lock(pthread_mutex_t *mutex);

     

    解锁

    int pthread_mutex_unlock(pthread_mutex_t * mutex);

     

    销毁互斥锁

    int pthread_mutex_destroy(pthread_mutex_t *mutex);

     

    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
    #include <unistd.h>
     
    pthread_mutex_t mutex;
    // print
    void printer(char *str)
    {
        pthread_mutex_lock(&mutex);
        while(*str!='\0')
        {
            putchar(*str);    
            fflush(stdout);
            str++;
            sleep(1);
        }
        printf("\n"); 
        pthread_mutex_unlock(&mutex);
    }
     
    // thread one
    void *thread_fun_1(void *arg)
    {
        char *str = "hello";
        printer(str); 
    }
     
    // thread two
    void *thread_fun_2(void *arg)
    {
        char *str = "world";
        printer(str); 
    }
     
    int main(void)
    {
        pthread_t tid1, tid2;
        int err1, err2;
            pthread_mutex_init(&mutex, NULL);
        // creat two thread
        err1 = pthread_create(&tid1, NULL, thread_fun_1, NULL);
        err2 = pthread_create(&tid2, NULL, thread_fun_2, NULL);
        // wait thread end
        pthread_join(tid1, NULL);
        pthread_join(tid2, NULL); 
        pthread_mutex_destroy(&mutex);
        return 0;
    }

     

    展开全文
  • 互斥锁演示

    2018-03-30 14:33:07
    演示了互斥锁的原因,演示了互斥锁的原因,演示了互斥锁的原因
  • 互斥锁:mutex,用于保证在任何时刻,都只能有一个线程访问该对象。当获取锁操作失败时,线程会进入睡眠,等待锁释放时被唤醒 读写锁:rwlock,分为读锁和写锁。处于读操作时,可以允许多个线程同时获得读操作。但是...

    Linux的4种锁机制:

    互斥锁:mutex,用于保证在任何时刻,都只能有一个线程访问该对象。当获取锁操作失败时,线程会进入睡眠,等待锁释放时被唤醒

    读写锁:rwlock,分为读锁和写锁。处于读操作时,可以允许多个线程同时获得读操作。但是同一时刻只能有一个线程可以获得写锁。其它获取写锁失败的线程都会进入睡眠状态,直到写锁释放时被唤醒。 注意:写锁会阻塞其它读写锁。当有一个线程获得写锁在写时,读锁也不能被其它线程获取;写者优先于读者(一旦有写者,则后续读者必须等待,唤醒时优先考虑写者)。适用于读取数据的频率远远大于写数据的频率的场合。

    自旋锁:spinlock,在任何时刻同样只能有一个线程访问对象。但是当获取锁操作失败时,不会进入睡眠,而是会在原地自旋,直到锁被释放。这样节省了线程从睡眠状态到被唤醒期间的消耗,在加锁时间短暂的环境下会极大的提高效率。但如果加锁时间过长,则会非常浪费CPU资源。

    RCU:即read-copy-update,在修改数据时,首先需要读取数据,然后生成一个副本,对副本进行修改。修改完成后,再将老数据update成新的数据。使用RCU时,读者几乎不需要同步开销,既不需要获得锁,也不使用原子指令,不会导致锁竞争,因此就不用考虑死锁问题了。而对于写者的同步开销较大,它需要复制被修改的数据,还必须使用锁机制同步并行其它写者的修改操作。在有大量读操作,少量写操作的情况下效率非常高。

    互斥锁和读写锁的区别:

    1)读写锁区分读者和写者,而互斥锁不区分

    2)互斥锁同一时间只允许一个线程访问该对象,无论读写;读写锁同一时间内只允许一个写者,但是允许多个读者同时读对象。

    死锁

    所谓死锁,是指多个进程在运行过程中因争夺资源而造成的一种僵局,当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进。

    产生死锁的四个必要条件

    1) 互斥条件:一个资源每次只能被一个进程使用。
    2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
    3) 不可剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
    4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

    展开全文
  • 添加互斥锁2添加递归互斥锁三.互斥锁1.代码2.测试四.递归互斥锁1.代码2.测试 FreeRTOS系统 一.简绍 互斥锁,谁获得的消息谁来释放 递归互斥锁,可以连续获得两次,同时释放的时候也释放两次 二.STM32CubMx配置 1....

    FreeRTOS系统

    一.简绍

    互斥锁,谁获得的消息谁来释放
    递归互斥锁,可以连续获得两次,同时释放的时候也释放两次

    二.STM32CubMx配置

    1.准备

    在这里插入图片描述

    2.添加互斥锁

    在这里插入图片描述

    2添加递归互斥锁

    在这里插入图片描述
    在这里插入图片描述

    三.互斥锁

    1.代码

    void StartDefaultTask_KEY1(void const * argument)
    {
    
      osSemaphoreId semaphore = (osSemaphoreId) argument;
    	for(;;)
      {
    		if(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == 1 )
    		{
    			osDelay(10);
    			if(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == 1 )
    			{
    				osThreadSuspendAll(); 
    				printf("\nkey1按下\n");
    				osThreadResumeAll();
    				osThreadResume(myTask01Handle);
    				osThreadResume(myTask02Handle);
    				
    				//=================获得====================
    				if(osMutexWait(myMutex011Handle, osWaitForever) == osOK)
    				{
    					osThreadSuspendAll(); 
    					printf("获得成功\n");
    					osThreadResumeAll();
    				}
    				else
    				{
    					osThreadSuspendAll(); 
    					printf("获得失败\n");
    					osThreadResumeAll();
    				}
    				
    					
    				//=================释放====================
    				if(osMutexRelease(myMutex011Handle) == osOK)
    				{
    					osThreadSuspendAll(); 
    					printf("释放成功\n");
    					osThreadResumeAll();
    				}
    				else
    				{
    					osThreadSuspendAll(); 
    					printf("释放失败\n");
    					osThreadResumeAll();
    				}
    			
    				while(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == 1)
    				{
    					osDelay(1);
    				
    				}
    			}
    		}
        osDelay(1);
      }
      /* USER CODE END StartDefaultTask_KEY1 */
    }
    
    void StartTask01(void const * argument)
    {
      /* USER CODE BEGIN StartTask01 */
      /* Infinite loop */
      for(;;)
      {
    		osThreadSuspend(NULL);
    		osThreadSuspendAll(); 
    		printf("我是任务1\n");
    		osThreadResumeAll();
        	osDelay(1);
      }
      /* USER CODE END StartTask01 */
    }
    
    void StartTask02(void const * argument)
    {
      /* USER CODE BEGIN StartTask02 */
      /* Infinite loop */
      for(;;)
      {
    	osThreadSuspend(NULL);
    	osThreadSuspendAll(); 
    	printf("我是任务2\n");
    	osThreadResumeAll();
    	osDelay(1);
      }
      /* USER CODE END StartTask02 */
    }
    
    

    只能获得一次释放一次,只有在释放完成后才可以大家都共享信号量

    2.测试

    在这里插入图片描述

    当存在获取两次信号的时候,就会阻塞

    四.递归互斥锁

    1.代码

    void StartDefaultTask_KEY1(void const * argument)
    {
    
      osSemaphoreId semaphore = (osSemaphoreId) argument;
    	for(;;)
      	{
    		if(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == 1 )
    		{
    			osDelay(10);
    			if(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == 1 )
    			{
    				osThreadSuspendAll(); 
    				printf("\nkey1按下\n");
    				osThreadResumeAll();
    				osThreadResume(myTask01Handle);
    				osThreadResume(myTask02Handle);
    				
    				//=================获得====================
    				if(osRecursiveMutexWait(myRecursiveMutex01Handle, osWaitForever) == osOK)
    				{
    					osThreadSuspendAll(); 
    					printf("获得成功\n");
    					osThreadResumeAll();
    				}
    				else
    				{
    					osThreadSuspendAll(); 
    					printf("获得失败\n");
    					osThreadResumeAll();
    				}
    				//=================获得====================
    				if(osRecursiveMutexWait(myRecursiveMutex01Handle, osWaitForever) == osOK)
    				{
    					osThreadSuspendAll(); 
    					printf("获得成功\n");
    					osThreadResumeAll();
    				}
    				else
    				{
    					osThreadSuspendAll(); 
    					printf("获得失败\n");
    					osThreadResumeAll();
    				}
    				
    					
    				//=================释放====================
    				if(osRecursiveMutexRelease(myRecursiveMutex01Handle) == osOK)
    				{
    					osThreadSuspendAll(); 
    					printf("释放成功\n");
    					osThreadResumeAll();
    				}
    				else
    				{
    					osThreadSuspendAll(); 
    					printf("释放失败\n");
    					osThreadResumeAll();
    				}
    				//=================释放====================
    				if(osRecursiveMutexRelease(myRecursiveMutex01Handle) == osOK)
    				{
    					osThreadSuspendAll(); 
    					printf("释放成功\n");
    					osThreadResumeAll();
    				}
    				else
    				{
    					osThreadSuspendAll(); 
    					printf("释放失败\n");
    					osThreadResumeAll();
    				}
    				while(HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == 1)
    				{
    					osDelay(1);
    				
    				}
    			}
    		}
        osDelay(1);
      }
      /* USER CODE END StartDefaultTask_KEY1 */
    }
    

    2.测试

    在这里插入图片描述

    展开全文
  • 互斥锁 自旋锁

    2019-03-26 18:12:34
    Cas是无锁机制 乐观锁。自旋锁 互斥锁 被关锁 syn锁 悲观锁 自旋锁 效率 远高于 互斥锁
  • 互斥锁(为了实现多个线程对同一共享资源的争用管理) 在多任务操作系统中,同时运行的多个任务可能都需要使用同一种资源。这个过程有点类似于,多人共用一台打印机,为了使大家都能有序公正的使用这台打印机,肯定...
  • python基础-进程互斥锁、线程互斥锁

    千次阅读 2017-12-04 20:11:13
    进程join引入互斥锁 进程互斥锁 购票例子进程互斥锁 线程互斥锁 mutex的简写形式进程错乱多进程共享同一套文件系统,访问同一个文件,或同一个打印终端,是没有问题的 但是进程之间数据不共享,多个进程共同操作数据会...
  • 使用mutex(互斥量、互斥锁)一般步骤: pthread_mutex_init 函数 初始化一个互斥锁(互斥量) —> 初值可看作1 int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr...
  • POSIX 之互斥锁(mutex)、互斥锁属性 0 引言 在多线程程序设计时不可避免地会遇到线程同步问题,最常用的操作就是进行加锁,通过加锁来保证数据的准确性,在所有加锁方式中最简单、最常用也就是mutex锁,本博文将...
  • 互斥锁和读写锁

    2020-03-07 15:07:48
    互斥锁的类型 pthread_mutex_t mutex 互斥锁的特点 多个线程访问资源的时候是串行的 互斥锁的使用步骤 创建一个互斥锁:pthread_mutex_t mutex 初始化这把锁:pthread_mutex_init(&mutex, NULL); ...
  • FreeRTOS互斥锁

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

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

    2020-09-01 14:08:42
    互斥锁:指的是同一时刻只能有一个线程获得互斥锁,其余试图请求该互斥锁的线程将会被挂起,不占用CPU资源,直到前面的线程释放了该互斥锁,其余线程才会被唤醒。 它只有两种状态:上锁和解锁。可以用来控制对共享...
  • 一、自旋锁和互斥锁的实现基于硬件原语的一些抽象(比如:中断禁用、原子操作指令),怎么实现?可以参考清华大学操作公开课(向勇、陈渝老师讲的),以下摘抄一部分实现代码来实现抽象。Test And Setbool Test_And_Set...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 26,975
精华内容 10,790
热门标签
关键字:

互斥锁