同步与互斥(三)

发布时间:2023年12月26日

一、递归锁

/* 创建一个递归锁,返回它的句柄。
* 此函数内部会分配互斥量结构体
* 返回值: 返回句柄,非NULL表示成功
*/
SemaphoreHandle_t xSemaphoreCreateRecursiveMutex( void );

/* 释放 */
BaseType_t xSemaphoreGiveRecursive( SemaphoreHandle_t xSemaphore );

/* 获得 */
BaseType_t xSemaphoreTakeRecursive(
            SemaphoreHandle_t xSemaphore,
            TickType_t xTicksToWait
);

static void vTakeTask( void *pvParameters )
{
	const TickType_t xTicksToWait = pdMS_TO_TICKS( 100UL );	
	BaseType_t xStatus;
	int i;

	
	/* 无限循环 */
	for( ;; )
	{	
		/* 获得递归锁: 上锁 */
		xStatus = xSemaphoreTakeRecursive(xMutex, portMAX_DELAY);
		printf("Task1 take the Mutex in main loop %s\r\n", \
			(xStatus == pdTRUE)? "Success" : "Failed");

		/* 阻塞很长时间, 让另一个任务执行, 
		 * 看看它有无办法再次获得递归锁 
		 */
		vTaskDelay(xTicksToWait);

		for (i = 0; i < 10; i++)
		{
			/* 获得递归锁: 上锁 */
			xStatus = xSemaphoreTakeRecursive(xMutex, portMAX_DELAY);
			
			printf("Task1 take the Mutex in sub loop %s, for time %d\r\n", \
				(xStatus == pdTRUE)? "Success" : "Failed", i);

			/* 释放递归锁 */
			xSemaphoreGiveRecursive(xMutex);
		}
		
		/* 释放递归锁 */
		xSemaphoreGiveRecursive(xMutex);
	}
}

static void vGiveAndTakeTask( void *pvParameters )
{
	const TickType_t xTicksToWait = pdMS_TO_TICKS( 10UL );	
	BaseType_t xStatus;

	/* 尝试获得递归锁: 上锁 */
	xStatus = xSemaphoreTakeRecursive(xMutex, 0);
	printf("Task2: at first, take the Mutex %s\r\n", \
		(xStatus == pdTRUE)? "Success" : "Failed");
	
	/* 如果失败则监守自盗: 开锁 */
	if (xStatus != pdTRUE)
	{
		/* 无法释放别人持有的锁 */
		xStatus = xSemaphoreGiveRecursive(xMutex);
		printf("Task2: give Mutex %s\r\n", \
			(xStatus == pdTRUE)? "Success" : "Failed");
	}

	/* 如果无法获得, 一直等待 */
	xStatus = xSemaphoreTakeRecursive(xMutex, portMAX_DELAY);
	printf("Task2: and then, take the Mutex %s\r\n", \
		(xStatus == pdTRUE)? "Success" : "Failed");
	
	/* 无限循环 */
	for( ;; )
	{	
		/* 什么都不做 */
		vTaskDelay(xTicksToWait);
	}
}

?main函数:

SemaphoreHandle_t xMutex;

int main( void )
{
	prvSetupHardware();
	
    /* 创建递归锁 */
    xMutex = xSemaphoreCreateRecursiveMutex( );

	if( xMutex != NULL )
	{
		/* 创建2个任务: 一个上锁, 另一个自己监守自盗(开别人的锁自己用)
		 */
		xTaskCreate( vTakeTask, "Task1", 1000, NULL, 2, NULL );
		xTaskCreate( vGiveAndTakeTask, "Task2", 1000, NULL, 1, NULL );

		/* 启动调度器 */
		vTaskStartScheduler();
	}
	else
	{
		/* 无法创建递归锁 */
	}

	/* 如果程序运行到了这里就表示出错了, 一般是内存不足 */
	return 0;
}

A:任务1优先级最高,先运行,获得递归锁
B:任务1阻塞,让任务2得以运行


C:任务2运行,看看能否获得别人持有的递归锁:不能
D:任务2故意执行"give"操作,看看能否释放别人持有的递归锁:不能


E:任务2等待递归锁
F:任务1阻塞时间到后继续运行,使用循环多次获得、释放递归锁
递归锁在代码上实现了:谁持有递归锁,必须由谁释放。

?

文章来源:https://blog.csdn.net/weixin_57604904/article/details/135164330
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。