linux线程同步:互斥锁

Linux线程同步机制详解:互斥锁、条件变量与读写锁 线程同步是多线程编程中的核心概念,用于解决共享资源访问时的数据竞争问题。其基本原理是通过协调线程执行顺序,确保对临界区的互斥访问。在Linux系统中,常见的同步机制包括互斥锁、条件变量、读写锁和信号量等,它们各自针对不同的应用场景进行了优化。互斥锁(Mutex)作为最基础的同步原语,通过简单的加锁/解锁操作实现资源独占访问;条件变量(Condition Variable)则提供了更灵活的线程间通信能力,常与互斥锁配合使用实现复杂的等待/通知机制。这些同步技术在开发高性能服务器、数据库系统等并发应用中具有重要 阅读详情

互斥锁(互斥量)是线程用来同步彼此行为的工具。互斥锁可以帮助线程同步对共享资源的使用,以防如下情况发生:线程某甲试图访问一共享变量时,线程某乙正在对其修改。

未避免线程更新共享变量时所出现的问题,必须使用互斥锁来确保同时仅有一个线程可以访问某项共享资源。

互斥锁有两种状态:已锁定(locked)和未锁定(unlocked)。任何时候,至多只有一个线程可以锁定该互斥锁。试图对已经锁定的某一互斥量再次加锁,将可能阻塞线程或者报错失败,具体取决于加锁时使用的方法。一旦线程锁定互斥锁,随机成为该互斥锁的所有者,只有所有者才能给互斥锁解锁。


互斥锁初始化:

互斥锁是属于pthread_mutex_t类型的变量,使用之前必须对其初始化。

初始化有两种方式:一种是静态赋值法,另一种是动态初始化。

静态赋值法只适用于静态分配的互斥量,如静态变量和全局变量定义的方式,且只能赋值普通锁

赋值形式:pthread_mutex_t mutex= PTHREAD_MUTEX_INITIALIZER

PTHREAD_MUTEX_INITIALIZER是指将互斥锁初始化为普通锁。锁的不同种类在下面会讲到。


动态初始化互斥锁是通过pthread_mutex_init函数初始化互斥锁,该函数原型如下:

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

动态初始化互斥锁适用于以下情况:

1.动态分配于堆中的互斥锁。

2.互斥锁是在栈中分配的自动变量。

3.初始化经由静态分配,但不使用默认属性的普通锁

以上情况只能用动态初始化函数初始化互斥锁。


函数中的参数mutexattr表示互斥锁的属性,如果为NULL则使用默认属性(普通锁)。互斥锁的属性及意义如下:

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



初始化以后,就可以对互斥锁进行加锁和解锁操作了。

锁操作主要包括加锁pthread_mutex_lock()、解锁pthread_mutex_unlock()和测试加锁 pthread_mutex_trylock()三个,不论哪种类型的锁,都不可能被两个不同的线程同时得到,而必须等待解锁。

加锁:

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

用pthread_mutex_lock()加锁时,如果mutex已经被锁住,当前尝试加锁的线程就会阻塞,直到互斥锁被其他线程释放。
pthread_mutex_trylock()语义与pthread_mutex_lock()类似,不同的是在锁已经被占据时返回EBUSY而不是挂起等待。

解锁:

int pthread_mutex_unlock(pthread_mutex_t *mutex)

解锁时要满足两个条件:

一是互斥锁必须处于加锁状态,二是调用本函数的线程必须是给互斥锁加锁的进程。


摧毁互斥锁:

当不再需要经由自动或动态分配的互斥锁时,应使用pthread_mutex_destory()将其摧毁。(对于使用PTHREAD_MUTEX_INITIALIZER静态初始化的互斥锁,无需调用pthread_mutex_destory())。

#include<pthread.h>

int pthread_mutex_destory(pthreead_mutex_t* mutex);


以下是一个利用互斥锁的一个例子:

#include <stdio.h>  
#include <stdlib.h>  
#include <pthread.h>  
  
#define THREAD_NUM 3  
#define REPEAT_NUM 3  
#define DELAY_TIME_LEVLES 5.0  
  
pthread_mutex_t mutex;  
  
void *thread_fun(void *arg)  
{  
    int no = (int) arg;  
    int delay;  
    int ret,i;  
  
    ret = pthread_mutex_lock(&mutex);  //返回0为成功  
    if(ret)  
    {  
        printf("Thread %d lock failed\n",no);  
        pthread_exit(NULL);  
    }  
  
    for(i=0;i<REPEAT_NUM;i++)  
    {  
        delay = (int)(rand()*DELAY_TIME_LEVELS/(RAND_MAX))+1;  
        sleep(delay);  
        printf("Thread %d: job %d delay = %d\n",no,i,delay);  
    }  
    printf("Thread %d finished\n",no);  
    pthread_exit  
}  
  
int main()  
{  
    pthread_t thread[THREAD_NUM];  
    int i,ret;  
    void *thrd;  
  
    srand(time(NULL));  
  
    pthread_mutex_init(&mutex,NULL);  
  
    for(i=0;i<THREAD_NUM;i++)  
    {  
        ret = pthread_create(&thread[i],NULL,thread_fun,(void *)i);  
        if(ret!=0)  
        {  
            printf("Create %d failed\n",i);  
            exit(ret);  
        }  
    }  
  
    printf("Create thread success!\n Waiting for threads to finish ...\n");  
  
    for(i=0;i<THREAD_NUM;i++)  
    {  
        ret = pthread_join(thread[i],&thrd);  
        pthread_mutex_unlock(&mutex);  
    }  
    pthread_mutex_destroy(&mutex);  
    return 0;  
}  


死锁现象:

死锁 (deallocks): 是指两个或两个以上的进程(线程)在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程(线程)称为死锁进程(线程)。


接下来介绍两个典型死锁现象例子,写程序时应避免此类现象。

1.线程发起pthread_mutex_lock()后,未解锁再次调用pthread_mutex_lock()进行上锁。此时线程会陷入无限等待状态。

2.线程A                                                               线程B

1.pthread_mutex_lock(&mutex1);                   1.pthread_mutex_lock(&mutex2);

2.pthread_mutex_lock(&mutex2);                   2.pthread_mutex_lock(&mutex1);

这两个线程中的每个线程都成功地锁住一个互斥量,接着试图对己为另一个线程锁定的互斥量加锁。两个线程将无限期地等待下去。


要避免此类死锁问题,最简单的方法是定义互斥量的层次关系。当多个线程对一组互斥量操作时,总是应该以相同的顺序对该组互斥量进行锁定。









Linux之线程同步二 在上一个实训中,我们学习了使用互斥锁来实现线程的同步,Linux系统中还提供了另一个类似互斥锁的线程不同操作,那就是信号量。本关任务:学会使用信号量来实现线程间的同步与互斥。 第2关:读写锁 当有一个数据即可以被读取,又可以被修改时,为了保证数据的一致性,最简单的方法是通过互斥锁对数据进行加锁操作。但是互斥锁的缺点是一旦数据被加锁后,只能有一个读线程或写线程来执行,而我们实际想要的效果是,同一时刻只能有一个线程对数据进行修改,而同一时刻可以有多个线程对其进行读取操作。那么互斥锁就无法满足我们的需求。Linu 阅读详情

相关推荐

Linux线程同步之互斥锁

一、我们知道,同一个进程中的所有线程是共享进程资源的。因此多线程中,线程同步则成为了一个很重要的话题。所谓“同步”,即“协同步调,按预定的先后次序进行运行”。所以“既需要在线程间共享数据,又需要以一致的顺序在线程间执行一组操作”。则必须借助于线程的同步手段、机制来实现。线程同步方法较多,常用到的有:互斥锁、条件变量(配合互斥锁)、信号量、读写锁、自旋锁等。其中互斥锁是所有“线程同步”手段中最为简单...

Postgres 数据库内核开发工程师 772

头歌 计算机操作系统 Linux之线程同步二

头歌 计算机操作系统 Linux之线程同步二编程题

安年的小小博客有大大的梦想 2203

手把手教你用DLP4500投影仪玩转结构光3D扫描(附固件烧录与序列设置避坑指南)

本文详细解析了如何使用DLP4500投影仪搭建结构光3D扫描系统,涵盖硬件组装、固件烧录、图案生成与优化等全流程。重点解决了固件烧录失败、图像格式错误等常见问题,并提供了实用的避坑指南和进阶技巧,帮助读者快速掌握DLP4500在3D扫描中的应用。

weixin_42662293的博客 301

【Linux系统编程二十七】:线程的互斥与同步(互斥锁的使用与应用)

【Linux系统编程二十七】:本文主要总结什么是互斥,为什么要互斥,以及互斥如何实现,主要原因是因为多线程并发访问共享资源,会造成数据不一致问题。介绍互斥锁的概念和相关接口使用,锁的应用场景,探讨同步场景下又该如何解决以及死锁问题。

Extreme_wei的博客 1219

百度新闻评论内容抓取

通过抓包分析发现,百家号手机app端文章评论内容接口为:https://ext.baidu.com/api/comment/v1/comment/getlist?appid=101&sid=1008524_2-1010050_1-1007549_23033-1007550_23035&cuid=01B5EAF73E8A83BB842BE04E4FB6C656|23200201047...

codingforhaifeng的博客 2420

MATLAB实战:手把手教你搭建构网逆变器同步稳定性仿真模型(附避坑指南)

本文详细介绍了如何在MATLAB/Simulink平台上搭建构网逆变器同步稳定性仿真模型,涵盖从基础模块配置到虚拟同步机控制实现的完整流程。针对电力电子工程师常见的控制参数整定困难、仿真结果偏差等问题,提供了LCL滤波器谐振抑制、虚拟惯量优化等关键技术解决方案,并附有避坑指南和工程实践技巧,助力研究者高效完成仿真建模。

weixin_29051193的博客 297

【Linux】多线程--互斥锁

文章目录前言基础概念互斥量mutex多线程模拟抢票(没加锁情况)为何多线程访问临界资源是不安全互斥锁相关接口多线程模拟抢票(有加锁)互斥锁实现的基本原理 前言 为什么线程需要同步和互斥的操作? 因为线程引入共享了进程的地址空间,导致了一个线程操作数据时候,极其容易影响到其他线程的情况;对其他线程造成不可控因素,或引起异常,逻辑结果不正确的情况;这也是线程不安全的原因! 如何创建一个线程安全函数?只要尽量不使用全局变量,stl,malloc,new 等操作即可;如果要使用,就要控制同步和互斥问题! 基础概念

呋喃吖的博客 1万+

windows10系统上安装最新版mysql 8.0详细步骤

windows10系统上安装最新版mysql 8.0详细步骤

glei20的博客 6715

Linux 线程同步之一:互斥锁

<br />在单线程条件下,由于对数据操作,在同样的时间下,只有一个线程来操作。所以不用担心数据的同步问题。现代的操作系统,大都提供并发机制,虽然有时候是表面的并发。在Linux中,并发用的最多的是基于线程的并发,进程的代价太高了,这样,一个共享的数据,在同一时间内,可能有多个线程在操作。如果没有同步机制,那么想要保证每个线程操作的正确性,是很困难的。<br />1互斥锁概念:<br />互斥锁提供一个可以在同一时间,只让一个线程访问临界资源的的操作接口。互斥锁(Mutex)是个提供线程同步的基本锁。让上锁

Harry的专栏 1万+

REST-meta-MDD Data总结

sMRI数据使用:nwc1、nwc2、nwc3(同样数据集相关论坛中有相关信息指向需要使用wc1、wc2、wc3)多方咨询与讨论后决定使用nwc数据,这里说明wc数据相对wc数据要大的多如wc1的大小为1.33GB,而nwc1的数据却有6.90GB。VBM文件:/REST-meta-MDD/Sharing/REST-meta-MDD-VBM- phase1 -Sharing.tar.gz。1、Excel中的表型信息:1-男,2-女;-9999或空白表示缺少数据。

2404_88295660的博客 1532

1.STM32H743VGT6最小系统板

此款MCU具备较大算力进行频谱运算,为复杂数据运算提供更高效的保障。该MCU具备REV-V和REV-Y两个型号,后者为新版本。

Audiation88的博客 3794

linux下的线程同步:互斥锁

假设有两个线程不加约束地对一个共享变量进行访问会有怎样的后果?这里myCallback1线程和myCallback2线程打算各对num加50次。但是,如果线程myCallback1在执行tmp = num后,myCallback2抢走CPU,也执行了这条语句,那么它就只能通过tmp自增一次而不是两次。为了不让线程同时访问到临界资源num,我们需要让它们“互斥”访问。

m0_74409155的博客 307

【教程4>第7章>第6节】基于FPGA的Viterbi维特比译码verilog实现——ACS加比选单元1

本文介绍了ACS加比选单元模块在FPGA中的实现过程,重点讲解了维特比译码中的ACS单元功能及其在硬件实现中的关键问题。文章首先概述了ACS单元在维特比译码中的作用,即通过计算和比较分支度量值来选择最优路径。接着,详细描述了FPGA实现中的分支度量值归一化处理策略,并指出了其存在的弊端。随后,文章提供了基于Verilog的ACS加比选单元模块代码,解释了其输入输出端口及工作流程。最后,总结了本小节内容,并预告了下一章节将涉及ACS顶层模块的开发与仿真测试。

FPGA/MATLAB学习教程/源码/项目合作开发 568

Linux学习日记19:线程同步与互斥锁

本文介绍了多线程编程中的线程同步技术,重点讲解了互斥锁的实现机制。首先通过一个反面案例展示了多线程并发访问共享资源时可能出现的数据不一致问题,说明线程同步的必要性。接着详细阐述了互斥锁的定义、底层实现原理及相关API函数的使用方法,包括静态/动态初始化、阻塞/非阻塞加锁、解锁等操作。最后通过代码示例演示了如何使用互斥锁解决线程竞争问题,确保对共享资源的原子访问。文章强调互斥锁是解决竞态条件、保证数据一致性的核心同步机制。

2201_75969037的博客 1443

华为OD机试真题2026双机位C卷 Java&Go 实现【用户入网定期复评】

用户开立支付账户,在开户完成后立即对用户进行一次风险模型评级,输出一个评分风险,评分范围1-100,等区间的分为5个等级,1-19为等级1,20-39为等级2,40-59为等级3,60-79为等级4,80-100为等级5,系统每天会任务对全量入网用户进行计算复评时间,输出评分给出新的风险等级。复评规则如下:

MISAYAONE的博客 147

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

嵌入式Linux:线程同步(互斥锁)

Linux线程的互斥锁(mutex)是用于保护共享资源的同步机制,确保在多线程环境中,多个线程不会同时访问或修改同一个资源,从而避免数据竞争或不一致的问题。

不脱发的程序猿 960

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Linux:线程同步机制(互斥锁、读写锁、条件变量、信号量详细分析总结)

Linux:线程同步机制(互斥锁、读写锁、条件变量、信号量详细分析总结)

qq_42279379的博客 2216

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

Linux线程同步实战:互斥锁、信号量与条件变量详解

在并发编程中,线程同步是确保多线程安全访问共享资源的核心机制。其基本原理是通过协调线程执行顺序,防止数据竞争和状态不一致。从技术价值看,有效的同步能提升程序健壮性、避免竞态条件,并充分利用多核性能。常见的应用场景包括服务器开发、数据库连接池管理以及任务队列处理。本文聚焦于Linux环境下三种关键同步工具:互斥锁用于保护临界区,实现独占访问;信号量作为资源计数器,管理多资源池;条件变量则结合互斥锁实现高效等待通知机制。通过生产者-消费者模型等实战案例,深入解析如何组合使用这些工具解决实际并发问题,并涵盖死锁预

weixin_30788239的博客 409

Linux:线程同步之互斥锁(互斥锁的本质、互斥锁的作用、如何使用互斥锁实现线程同步)

Linux:线程同步之互斥锁(互斥锁的本质、互斥锁的作用、如何使用互斥锁实现线程同步);pthread_mutex_init、pthread_mutex_lock、pthread_mutex_lock、pthread_mutex_unlock、pthread_mutex_destroy等

qq_42279379的博客 728

Linux线程间同步①:互斥锁Mutex

进程间通信往往意味着系统调用,内核态,用户态的切换,其代价是不容忽视的。而线程是进程中的具体执行流,一个进程中多个线程共享进程的资源,包含进程的虚拟地址空间,进程打开的文件描述符,进程组ID等。 而线程间的通信和同步由于处于同一地址空间下,也更加轻易和轻量级。 多线程之间访问共享变量时,这些共享变量若每次只能被一个线程进行访问,称为临界资源。而对临界资源的访问在多线程环境下,如果不加以控制,很容易出现不一致性。 最常见的便是多线程售票问题。由于每个线程在执行售票(取得票数=》扣款=》票数i--=》写回

一只老风铃 594

【Linux C/C++ 线程同步 】Linux互斥锁和条件变量:互斥锁和条件变量在Linux线程同步中的编程实践

线程同步和互斥描述 相交进程之间的关系主要有两种,同步与互斥。所谓互斥, 是指散步在不同进程之间的若干程序片断,当某个进程运行其中一个程序片段时,其它进程就不能运行它 们之中的任一程序片段,只能等到该进程运行完这个程序片段后才可以运行。 所谓同步, 是指散步在不同进程之间的若干程序片断,它们的运行必须严格按照规定的 某种先后次序来运行,这种先后次序依赖于要完成的特定的任务。 显然,同步是一种更为复杂的互斥,而互斥是一种特殊的同步。 互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一.

探索C++编程的奥秘,分享深入的技术见解和实践,旨在激发读者创造力与解决问题的思维。 1882

Linux C多线程编程:从互斥锁到信号量,一文搞定线程同步

pthread_mutex_lock() 的阻塞特性是:如果锁已经被其他线程持有,当前线程会一直等待,直到锁被释放。线程B也读到1张,也卖了一张——最后两张票卖给了两个人,票数变成了-1。互斥锁就像厕所的门锁——一个人进去之后锁上门,出来再开锁,下一个人才能进去。线程B持有锁2,等待锁1——两个人都在等对方先放手,结果谁也没法动。trylock 不会阻塞线程:如果锁被占用,立即返回错误码,线程可以释放已持有的锁、稍后重试。自旋锁的特点是:申请不到锁时,不会让出CPU,而是忙等待(一直循环检查锁是否可用)。

2602_96624055的博客 579

Linux系统编程-线程(二)-线程同步01:互斥锁

而在线程里也有这么一把锁:互斥锁(mutex),也叫互斥量,互斥锁是一种简单的加锁的方法来控制对共享资源的访问,互斥锁只有两种状态,即加锁( lock )和解锁( unlock )。互斥锁的操作流程如下:1)在访问共享资源后临界区域前,对互斥锁进行加锁。2)在访问完成后释放互斥锁导上的锁。3)对互斥锁进行加锁后,任何其他试图再次对互斥锁加锁的线程将会被阻塞,直到锁被释放。互斥锁的数据类型是: pthread_mutex_t。

u013250861的博客 580

Linux系统编程——线程同步与互斥:互斥锁

在多任务操作系统中,同时运行的多个任务可能都需要使用同一种资源。这个过程有点类似于,公司部门里,我在使用着打印机打印东西的同时(还没有打印完),别人刚好也在此刻使用打印机打印东西,如果不做任何处理的话,打印出来的东西肯定是错乱的。 实际上,打印机是有做处理的,我在打印着的时候别人是不允许打印的,只有等我打印结束后别人才允许打印。这个过程有点类似于,把打印机放在一个房间里,给这个房间安把锁,这个锁默认是打开的。当 A 需要打印时,他先过来检查这把锁有没有锁着,没有的话就进去,同时上锁在房间里打印。而在这时,刚

秋叶原 && Mike || 麦克 19万+

第三章 Linux进程线程:9.线程同步:互斥锁、信号量、条件变量

进程间与线程间通信- 通常用于进程间通信的方式,也可以用于线程间通信。- 信号量不仅适用于进程间同步,还可以用于线程间同步。无名信号量与有名信号量有名信号量:通过唯一的信号量名称标识,在操作系统中有唯一标识,适用于进程间通信。无名信号量:用于进程间通信时,信号量必须存储在共享的内存区域内,进程通过内存地址直接访问这些信号量。二进制信号量与计数信号量二进制信号量:用于互斥,通常充当互斥锁,确保资源的互斥访问。计数信号量:用于控制进程或线程的执行顺序,值的范围可以大于1,用于协调多个进程的顺序。

qq_62848032的博客 958

Days 32 Linux 多线程:线程分离属性、多进程 vs 多线程、线程同步互斥锁、信号量

在 Linux C 多线程开发中,默认创建出来的线程是可连接属性(joinable),这种线程在线程退出之后,它的资源(线程栈、线程描述符)不会自动释放,必须调用去回收资源;如果不 join 就会产生僵尸线程,造成内存资源泄漏。而线程分离属性 (detach)就是用来解决这个问题的。本篇博客基于 Linux 下 pthread 库,讲解线程分离属性、多进程与多线程对比、线程间通信、互斥锁、死锁、信号量相关知识点。环境:Ubuntu,gcc 编译需要增加-pthread链接选项。

Q3365879的博客 183
上一篇: linux 进程的虚拟内存
下一篇: linux线程同步:条件变量
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值