嵌入式Linux并发程序设计,线程,线程间通信--互斥,临界资源/临界区/互斥机制/互斥锁,pthread_mutex_init()/pthread_mutex_lock/unlock()

1,临界资源

  1. 临界资源
    · 一次只允许一个任务(进程、线程)访问的共享资源
  2. 临界区
    ·访问临界资源的代码
    ·访问非临界资源的代码叫非临界区
  3. 互斥机制
    ·临界区互斥:当一个任务在访问临界区的时候,其他任务不能访问该临界区(相同的临界资源)
    ·mutex互斥锁:互斥锁只能被一个任务所持有。互斥锁有两种状态,空闲/只被一个任务所持有。
    ·任务访问临界资源前申请锁,访问完后释放锁。没有申请到锁的任务需要阻塞等待,直到持有这个锁为止

2,互斥锁的初始化pthread_mutex_init()

#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *mutex,const pthread_mutexattr_t * attr);

  1. 成功时返回0,失败时返回错误码
  2. mutex 指向要初始化的互斥锁对象
  3. attr 互斥锁属性,NULL表示缺省属性

3,申请锁pthread_mutex_lock()

#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex);

  1. 成功时返回0,失败时返回错误码
  2. mutex 指向要初始化的互斥锁对象
  3. 如果无法获得锁,任务阻塞

4,释放锁pthread_mutex_unlock()

#include <pthread.h>
int pthread_mutex_unlock(pthread_mutex_t *mutex);

  1. 成功时返回0,失败时返回错误码
  2. mutex 指向要初始化的互斥锁对象
  3. 执行完临界区要及时释放锁
  4. 如果有多个临界资源,比如一个任务每次都要同时访问两个临界资源,那这两个临界资源只需要一个互斥锁保护就行。如果这两个临界资源访问不是同时的,就需要两个互斥锁来分别保护

5,线程互斥—示例

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <semaphore.h>

unsigned int count, value1, value2;
pthread_mutex_t lock;

void *function(void *arg);
int main(void) 
{
	pthread_t  a_thread;

	if (pthread_mutex_init(&lock, NULL) != 0) 
	{
		printf("fail to pthread_mutex_init\n");  exit(-1);
	}
	if (pthread_create(&a_thread, NULL, function, NULL) != 0) 
	{
		printf("fail to PTHREAD_CREATE_JOINABLEeate");  exit(-1); 
	}
	while ( 1 ) //主线程
	{
		count++;
#ifdef  _LOCK_
		pthread_mutex_lock(&lock);
#endif
		value1 = count;
		value2 = count;
#ifdef  _LOCK_
		pthread_mutex_unlock(&lock);
#endif
	}
		return 0;
}

void *function(void *arg) 
{
	while ( 1 ) 
	{
#ifdef  _LOCK_
		pthread_mutex_lock(&lock);
#endif
		if (value1 != value2) 
		{
			printf("value1 = %u, value2 = %u\n", value1, value2);
			usleep(100000);
		}
#ifdef  _LOCK_
		pthread_mutex_unlock(&lock);
#endif
	}
	return 	 NULL;  
}
  1. 主线程中count++,之后会先把count赋给value1,再把count赋给value2;另外一个线程每隔100ms执行一次判断value1!=value2,如果不等于,分别打印value1和value2;
  2. 如果不上锁,主线程把count赋给value1后,如果还没来得及赋给value2,主线程的时间片用完了,系统自动调度到另外一个线程,就会出现value1!=value2的情况
  3. 如果上了互斥锁,就能让两个线程中的临界区代码严格互斥

不使用互斥锁gcc sem3.c -o sem3.out -lpthread

linux@linux:~/test/pthread$ gcc sem3.c -o sem3.out -lpthread
linux@linux:~/test/pthread$ ./sem3.out 
value1 = 3052903, value2 = 3052902
value1 = 38157180, value2 = 38157179
value1 = 72179985, value2 = 72179984
value1 = 107488282, value2 = 107488281
value1 = 141249026, value2 = 141249025
value1 = 171859486, value2 = 171859485

使用互斥锁gcc sem3.c -o sem3.out -lpthread -D_LOCK_

linux@linux:~/test/pthread$ gcc sem3.c -o sem3.out -lpthread -D_LOCK_
linux@linux:~/test/pthread$ ./sem3.out 

  1. "-D"相当于传入宏定义

猜你喜欢

转载自blog.csdn.net/m0_37542524/article/details/83866896
今日推荐