Linux线程间通信之互斥锁(十五)

1.同步与互斥概述

现代操作系统基本都是多任务操作系统,即同时有大量可调度实体在运行。在多任务操作系统中,同时运行的多个任务可能: 都需要访问/使用同一种资源 多个任务之间有依赖关系,某interesting两个问题的。 互斥:是指散步在不同任务之间的若干程序片断,当某个任务运行其中一个程序片段时,其它任务就不能运行它们之中的任一程序片段,只能等到该任务运行完这个程序片段后才可以运行。最基本的场景就是:一个公共资源同一时刻只能被一个进程或线程使用,多个进程或线程不能同时使用公共资源。
同步:是指散步在不同任务之间的若干程序片断,它们的运行必须严格按照规定的某种先后次序来运行,这种先后次序依赖于要完成的特定的任务。最基本的场景就是:两个或两个以上的进程或线程在运行过程中协同步调,按预定的先后次序运行。比如 A 任务的运行依赖于 B 任务产生的数据。 显然,同步是一种更为复杂的互斥,而互斥是一种特殊的同步。也就是说互斥是两个任务之间不可以同时运行,他们会相互排斥,必须等待一个线程运行完毕,另一个才能运行,而同步也是不能同时运行,但他是必须要按照某种次序来运行相应的线程(也是一种互斥)!因此互斥具有唯一性和排它性,但互斥并不限制任务的运行顺序,即任务是无序的,而同步的任务之间则有顺序关系。

2.互斥锁

互斥锁Mutex介绍 而在线程里也有这么一把锁:互斥锁(mutex),也叫互斥量,互斥锁是一种简单的加锁的方法来控制对共享资源的访问,互斥锁只有两种状态,即加锁( lock )和解锁( unlock )。

互斥锁的操作流程如下:
1)在访问共享资源后临界区域前,对互斥锁进行加锁。
2)在访问完成后释放互斥锁导上的锁。
3)对互斥锁进行加锁后,任何其他试图再次对互斥锁加锁的线程将会被阻塞,直到锁被释放。

互斥锁的数据类型是: pthreadmutext。
安装对应帮助手册: deng@itcast:~$ sudo apt-get install manpages-posix-dev

2.1.互斥锁初始化函数

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

功能:
初始化一个互斥锁。

参数:
mutex: 互斥锁地址。类型是 pthread_mutex_t 。
attr:设置互斥量的属性,通常可采用默认属性,即可将 attr 设为 NULL。

可以使用宏 PTHREAD_MUTEX_INITIALIZER 静态初始化互斥锁,比如:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
这种方法等价于使用 NULL 指定的 attr 参数调用 pthread_mutex_init() 来完成动态初始化,不同之处在于 PTHREAD_MUTEX_INITIALIZER 宏不进行错误检查。

返回值:
成功:0,成功申请的锁默认是打开的。
失败: 非0 ,错误码。

2.2.销毁互斥锁函数

	int pthread_mutex_destroy(pthread_mutex_t *mutex);

功能:
销毁指定的一个互斥锁。互斥锁在使用完毕后,必须要对互斥锁进行销毁,以释放资源。

参数:
mutex:互斥锁地址。

返回值:
成功:0.
失败: 非0 ,错误码。

2.3.申请上锁函数

	int pthread_mutex_lock(pthread_mutex_t *mutex);

功能:
对互斥锁上锁,若互斥锁已经上锁,则调用者阻塞,直到互斥锁解锁后再上锁。

参数:
mutex:互斥锁地址。

返回值:
成功:0.
失败: 非0 ,错误码。

说明:

	int pthread_mutex_trylock(pthread_mutex_t *mutex);
	调用该函数时,若互斥锁未加锁,则上锁,返回 0;
	若互斥锁已加锁,则函数直接返回失败,即 EBUSY

2.4.解锁函数

	int pthread_mutex_unlock(pthread_mutex_t *mutex);

功能:
对指定的互斥锁解锁。

参数:
mutex:互斥锁地址。

返回值:
成功:0.
失败: 非0 ,错误码。

3.参考代码

//=============================================================================
// File Name    : thread_mutex_lock.c
// Author       : FengQQ
//
// Description  : 互斥锁
// Annotation   : 1)在访问共享资源后临界区域前,对互斥锁进行加锁。
//				  2)在访问完成后释放互斥锁导上的锁。
//				  3)对互斥锁进行加锁后,任何其他试图再次对互斥锁加锁的线程将会被阻塞,
//					 直到锁被释放。
//
// Created by FengQQ. 2020-10-04
//=============================================================================
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <errno.h>

pthread_mutex_t mutex;

//-----------------打印函数-----------------
void print(char *str)
{
    
    
	//hello
	while(*str != 0)
	{
    
    
		putchar(*str++);
		fflush(stdout);
		sleep(1);
	}
	printf("\n");

}
//---------------线程1入口函数---------------
void *pthread1_callback(void *arg)
{
    
    
	char buf[]="hello";
	
	pthread_mutex_lock(&mutex);		//加锁
	print(buf);
	pthread_mutex_unlock(&mutex);	//解锁
}
//---------------线程2入口函数---------------
void *pthread2_callback(void *arg)
{
    
    
	char buf[]="world";

	pthread_mutex_lock(&mutex);		//加锁
	print(buf);
	pthread_mutex_unlock(&mutex);	//解锁
}

int main(int argc,char *argv[])
{
    
    
	int ret;
	pthread_t ptid1,ptid2;
	
	ret = pthread_mutex_init(&mutex,NULL);							//互斥锁初始化
	if(ret != 0)
	{
    
    
		printf("pthread mutex init failed...\r\n");
		return -1;
	}
	
	ret = pthread_create(&ptid1,NULL,pthread1_callback,	NULL);		//创建线程1
	if(ret != 0)
	{
    
    
		printf("create new pthread1 failed...\r\n");
		return -1;
	}
	
	ret = pthread_create(&ptid2,NULL,pthread2_callback,	NULL);		//创建线程2
	if(ret != 0)
	{
    
    
		printf("create new pthread2 failed...\r\n");
		return -1;
	}
	
	ret = pthread_join(ptid1,NULL);									//回收线程1资源
	if(ret != 0)
	{
    
    
		printf("pthread1 join failed...\r\n");
	}
	
	ret = pthread_join(ptid2,NULL);									//回收线程2资源
	if(ret != 0)
	{
    
    
		printf("pthread2 join failed...\r\n");
	}
	
	return 0;
}

Linux线程间通信之读写锁(十六)

链接: link.(https://blog.csdn.net/qq_39721016/article/details/120477798?spm=1001.2014.3001.5501)

猜你喜欢

转载自blog.csdn.net/qq_39721016/article/details/120477622