0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Linux下线程间通讯--互斥锁

嵌入式技术 来源:嵌入式技术 作者:嵌入式技术 2022-08-24 15:53 次阅读

Linux下线程间通讯--互斥锁

1.互斥锁简介

编程中,引入了对象互斥锁的概念,来保证共享数据操作的完整性。每个对象都对应于一个可称为" 互斥锁" 的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。

互斥锁(Mutex)是在原子操作API的基础上实现的信号量行为。互斥锁不能进行递归锁定或解锁,能用于交互上下文但是不能用于中断上下文,同一时间只能有一个任务持有互斥锁,而且只有这个任务可以对互斥锁进行解锁。

互斥锁是一种简单的加锁的方法来控制对共享资源的存取,当多个线程访问公共资源时,为了保证同一时刻只有一个线程独占资源,就可以通过互斥锁加以限制,在一个时刻只能有一个线程掌握某个互斥锁,拥有上锁状态的线程才能够对共享资源进行操作。若其他线程希望上锁一个已经上锁了的互斥锁,则该线程就会挂起,直到上锁的线程释放掉互斥锁为止。

2.互斥锁相关函数

在Posix Thread中定义有一套专门用于线程同步的mutex函数。可以通过静态和动态两种方式创建互斥锁。
互斥锁有三个类型可供选择:

PTHREAD_MUTEX_TIMED_NP普通锁(默认锁):

当一个线程加锁以后,其余请求锁的线程将形成一个阻塞等待队列,并在解锁后按优先级获得锁。这种锁策略保证了资源分配的公平性。

PTHREAD_MUTEX_RECURSIVE_NP嵌套锁:

允许同一个线程对同一个锁成功获得多次,并通过多次unlock 解锁。如果是不同线程请求,则在加锁线程解锁时重新竞争。
嵌套锁对同一线程可以重复上锁成功,对不同线程不能重复上锁。
嵌套锁在同一线程中重复上锁,需要重复解锁,否则其它线程将阻塞。

PTHREAD_MUTEX_ERRORCHECK_NP检错锁:

如果同一个线程请求同一个锁,则返回 EDEADLK,否则与普通锁类型动作相同。 这样就保证当不允许多次加锁时不会出现最简单情况下的死锁。

检错锁的主要特点就是: 同一个线程无法多次重复进行加锁, 第一次获取锁成功后, 没有解锁的情况下, 如果继续获取锁将不会阻塞, 会返回一个错误值(35)。

动态方式初始化互斥锁:
int pthread_mutex_init(pthread_mutex_t *restrict mutex,constpthread_mutexattr_t *restrict attr);
  attr填NULL表示使用默认属性,创建普通锁。
//静态方式初始化互斥锁
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
//互斥锁上锁,多次请求则会阻塞
int pthread_mutex_lock(pthread_mutex_t *mutex);
//互斥锁上锁,多次请求不会阻塞,会返回上锁失败错误信息
int pthread_mutex_trylock(pthread_mutex_t *mutex);
//互斥解锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);
//销毁互斥锁
int pthread_mutex_destroy(pthread_mutex_t *mutex);

3.互斥锁编程

3.1练习1

  1.创建1个线程,子线程先打印10遍hello,world,然后主线程再打印5遍”12346”,按次顺序循环50次。

#include 
#include 
#include 
/*
1.创建1个线程,子线程先打印10遍hello,world,然后主线程再打印5遍”12346”,按次顺序循环50次。
*/
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;//静态初始化互斥锁1
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;//静态初始化互斥锁2
void *pth_work(void *arg)
{
	int i,j;
	for(i=0;i<50;i++)
	{
		pthread_mutex_lock(&mutex);
		printf("-----------子线程第%d遍-----------\n",i);
		for(j=0;j<10;j++)
		{
			printf("hello,world\n");
		}
		pthread_mutex_unlock(&mutex2);
	}
}
int main()
{
	int i=0,j;
	pthread_t pthid;
	pthread_mutex_lock(&mutex2);
	/*创建子线程*/
	pthread_create(&pthid,NULL,pth_work,NULL);//创建线程
	pthread_detach(pthid);
	for(i=0;i<50;i++)
	{
		pthread_mutex_lock(&mutex2);//互斥锁上锁
		printf("-----------主线程第%d遍-----------\n",i);
		for(j=0;j<5;j++)//主线程打印
		{
			printf("123456\n");
		}
		pthread_mutex_unlock(&mutex);
	}
	pthread_mutex_destroy(&mutex);
	pthread_mutex_destroy(&mutex2);

}
pYYBAGMF2PKAWZXzAAHlP4bPJ8M761.png#pic_center

3.2练习2

  2.创建3线程,线程1打印A,线程2打印B,线程3打印C,按照ABC顺序输出10遍。

#include 
#include 
#include 
/*
2.创建3线程,线程1打印A,线程2打印B,线程3打印C,按照ABC顺序输出10遍。
*/
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;//静态初始化互斥锁1
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;//静态初始化互斥锁2
pthread_mutex_t mutex3 = PTHREAD_MUTEX_INITIALIZER;//静态初始化互斥锁3
void *pth_work(void *arg)
{
	int cnt=(int *)arg;
	//printf("cnt=%d\n",cnt);
	for(int i=0;i<10;i++)
	{
		if(cnt==0)//线程1
		{
			pthread_mutex_lock(&mutex);
			printf("A");
			pthread_mutex_unlock(&mutex2);
		}
		if(cnt==1)//线程2
		{
			pthread_mutex_lock(&mutex2);
			printf("B");
			pthread_mutex_unlock(&mutex3);
		}
		if(cnt==2)//线程3
		{
			pthread_mutex_lock(&mutex3);
			printf("C");
			fflush(stdout);//刷新缓冲区
			pthread_mutex_unlock(&mutex);
		}
	}
}
int main()
{
	int i=0;
	pthread_t pthid[3];
	pthread_mutex_lock(&mutex2);
	pthread_mutex_lock(&mutex3);
	/*创建3个子线程*/
	for(i=0;i<3;i++)
	{
		pthread_create(&pthid[i],NULL,pth_work,(void *)i);
	}
	/*等待线程结束*/
	for(i=0;i<3;i++)
	{
		pthread_join(pthid[i],NULL);
	}
	printf("\n所有子线程结束,程序退出!\n");
	pthread_mutex_destroy(&mutex);
	pthread_mutex_destroy(&mutex2);
	pthread_mutex_destroy(&mutex3);
}

运行效果:

[wbyq@wbyq ubuntu]$ ./app 
ABCABCABCABCABCABCABCABCABCABC
所有子线程结束,程序退出!

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Linux
    +关注

    关注

    87

    文章

    10991

    浏览量

    206742
  • 线程
    +关注

    关注

    0

    文章

    489

    浏览量

    19500
收藏 人收藏

    评论

    相关推荐

    Linux下线程编程

    Linux下线程编程
    的头像 发表于 08-24 15:42 1716次阅读

    Linux下线程通讯---读写锁和条件变量

    读写锁,它把对共享资源的访问者划分成读者和写者,读者只对共享资源进行读访问,写者则需要对共享资源进行写操作。件变量是线程可用的一种同步机制,条件变量给多个线程提供了一个回合的场所,条件变量和互斥量一起使用,允许
    的头像 发表于 08-26 20:44 1116次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>下线程</b>间<b class='flag-5'>通讯</b>---读写锁和条件变量

    详细谈谈Linux中的多线程同步和互斥机制

    互斥:多线程互斥是指多个线程访问同一资源时同时只允许一个线程对其进行访问,具有唯一性和排它性。但互斥
    的头像 发表于 03-20 09:09 1344次阅读

    Linux高级编程---互斥

    Linux系统里,有很多的应用,包括互斥,文件,读写等等,信号量其实也应该是
    发表于 01-13 10:07

    【MiCOKit试用体验】庆科MiCO系统篇(3)MiCO RTOS互斥

    示例MiCO互斥测试结果一、OS互斥锁上篇分析了信号量,而互斥,是一种特殊的信号量,常用来防止两个进程或
    发表于 10-24 17:02

    Linux线程线程同步

    ,可以指定返回值,以便其他线程通过pthread_join函数获取该线程的返回值。void *status:指针线程终止的返回值。4、线程
    发表于 12-08 14:14

    Linux C 多线程编程之互斥与条件变量实例详解

    一、互斥互斥量从本质上说就是一把, 提供对共享资源的保护访问。1. 初始化:在Linux下, 线程
    发表于 06-03 17:13

    Linux线程同步方法

    Linux下提供了多种方式来处理线程同步,最常用的是互斥、条件变量和信号量。
    发表于 07-19 07:24

    【HarmonyOS HiSpark AI Camera 】第三次回眸-鸿蒙的线程互斥

    / ... ad-0000001050141770提供的API进行编程。多线程在多核处理器可以加快运行时间,在单核处理器上没有什么优势。线程同步,最常用的是互斥、条件变量、信号量和读
    发表于 11-13 20:01

    Linux下的线程安全是什么

    数据二义性。同步与互斥:同步:通过条件判断,实现对灵界资源访问的时序合理性。互斥:通过唯一访问,实现对临界资源的安全性。一、互斥实现的技术:互斥
    发表于 07-01 13:34

    鸿蒙内核实现用户态快速互斥Futex设计资料合集

    Futex(Fast userspace mutex,用户态快速互斥),系列篇简称 快 ,是一个在 Linux 上实现锁定和构建高级抽象
    发表于 03-23 14:12

    Linux线程实现与线程控制步骤简析

    ,因此在对这些资源进行操作时,必须考虑到线程资源访问的惟一性问题,这里主要介绍 POSIX 中线程同步的方法,主要有互斥和信号量的方式。
    发表于 04-25 09:29

    Linux线程互斥互斥

    的同步问题, 线程同步的思路: 让多个线程依次访问共享资源,而不是并行互斥VS同步互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但
    发表于 04-02 14:47 201次阅读

    使用Linux互斥体实现互斥点灯

    互斥访问是指一次只有一个线程可以访问共享资源,不能递归申请互斥体。使用互斥体时要注意如下几点。
    的头像 发表于 04-13 15:13 669次阅读
    使用<b class='flag-5'>Linux</b><b class='flag-5'>互斥</b>体实现<b class='flag-5'>互斥</b>点灯

    Linux互斥锁的作用 互斥锁是什么

    1、互斥互斥锁(mutex),在访问共享资源之前对互斥锁进行上锁,在访问完成后释放互斥锁(解锁);对互斥锁进行上锁之后,任何其它试图再次
    的头像 发表于 07-21 11:13 569次阅读