linux线程-使用互斥量同步

互斥量:

允许程序员锁住某个对象,使得每次只能有一个线程访问它.

mutex是一种保证串行的睡眠锁,当无法获得锁时,mutex挂起当前线程,进入阻塞状态。正因为此,不能再中断上线文中使用。

不可以重复获取同一把锁,不可以多次释放同一把锁

在多进程中资源共享使使用,保护临界资源。在使用前加锁,使用后解锁。同时要避免死锁。

互斥量相关的函数

#include<pthread.h>
//初始化
int  pthread_mutex_init(pthread_mutex_t  mutex,const pthread_mutexattr_t *mutexattr);
//加锁
int pthread_mutex_lock(pthread_mutex_t  *mutex);
//解锁
int pthread_mutex_unlock(pthread_mutex_t  *mutex);
//销毁
int pthread_mutex_destroy(pthread_mutex_t  *mutex)

尝试获得锁的区别

//成功返回0,失败返回错误码。如果互斥量已经被其他线程锁住,会导致该线程阻塞

int pthread_mutex_lock(pthread_mutex_t *mutex);

//如果互斥量被锁住,这个函数不会阻塞线程

int pthread_mutex_trylock(pthread_mutex_t *mutex);

测试代码

实例中的临界区资源 work_area,time_to_exit
主线程获取输入,子线程统计字符串大小

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

void *thread_function(void *arg);
pthread_mutex_t work_mutex;
#define WORK_SIZE 1024

char work_area[WORK_SIZE];
int time_to_exit = 0;

int main()
{
	int res;
	pthread_t a_thread;
	void *thread_result;

	memset(work_area,0,sizeof(work_area));

	res = pthread_mutex_init(&work_mutex,NULL);
	if(res != 0)
	{
		perror("Semaphore initialization failed\n");
		exit(EXIT_FAILURE);
	}

	res = pthread_create(&a_thread,NULL,thread_function,NULL);
	if(res !=0)
	{
		perror("Thread creation failed");
		exit(EXIT_FAILURE);
	}
	pthread_mutex_lock(&work_mutex);
	printf("Input some txt,Enter 'end' to finish\n");
	while(!time_to_exit)
	{
		fgets(work_area,WORK_SIZE,stdin);
		pthread_mutex_unlock(&work_mutex);
		while(1)
		{
			pthread_mutex_lock(&work_mutex);
			if(work_area[0] != '\0')
			{
				pthread_mutex_unlock(&work_mutex);
				sleep(1);
			}
			else
				break;
		}
	}
	pthread_mutex_unlock(&work_mutex);
	printf("\n Waiting for thread to finish...\n");
	res = pthread_join(a_thread,&thread_result);
	if(res !=0)
	{
		perror("Thread join failed");
		exit(EXIT_FAILURE);
	}
	printf("Thread joined\n");
	pthread_mutex_destroy(&work_mutex);
	exit(EXIT_SUCCESS);
}

void *thread_function(void *arg)
{
	sleep(1);
	pthread_mutex_lock(&work_mutex);
	while(strncmp("end",work_area,3) != 0)
	{
		printf("You input %d characters\n",strlen(work_area) -1);
		work_area[0]='\0';
		pthread_mutex_unlock(&work_mutex);
		sleep(1);
		pthread_mutex_lock(&work_mutex);
		while(work_area[0] == '\0'){
			pthread_mutex_unlock(&work_mutex);
			sleep(1);
			pthread_mutex_lock(&work_mutex);
		}
	}
	time_to_exit = 1;
	work_area[0]='\0';
	pthread_mutex_unlock(&work_mutex);
	pthread_exit(0);
}

打印输出

(base) wy@ubuntu:~/process$ ./thread4 
Input some txt,Enter 'end' to finish
hello 
You input 5 characters
end

 Waiting for thread to finish...
Thread joined

子线程等待主线程的输入并统计输入字符串work_area的长度。
子线程在统计后将time_to_exit 置位,使主线程退出。

死锁举例

ABBA锁
1、进程之间
在一个线程中对已经加锁的普通锁再次加锁->死锁

#include <pthread.h>
#include <unistd.h>
#include <stdio.h>

int a = 0;
int b = 0;
pthread_mutex_t mutex_a;
pthread_mutex_t mutex_b;

void* another( void* arg )
{
    pthread_mutex_lock( &mutex_b );
    printf( "in child thread, got mutex b, waiting for mutex a\n" );
    sleep( 5 );
    ++b;
    pthread_mutex_lock( &mutex_a );
    b += a++;
    pthread_mutex_unlock( &mutex_a );
    pthread_mutex_unlock( &mutex_b );
    pthread_exit( NULL );
}

int main()
{
    pthread_t id;
    
    pthread_mutex_init( &mutex_a, NULL );
    pthread_mutex_init( &mutex_b, NULL );
    pthread_create( &id, NULL, another, NULL );

    pthread_mutex_lock( &mutex_a );
    printf( "in parent thread, got mutex a, waiting for mutex b\n" );
    sleep( 5 );
    ++a;
    pthread_mutex_lock( &mutex_b );
    a += b++;
    pthread_mutex_unlock( &mutex_b );
    pthread_mutex_unlock( &mutex_a );

    pthread_join( id, NULL );
    pthread_mutex_destroy( &mutex_a );
    pthread_mutex_destroy( &mutex_b );
    return 0;
}

主线程加锁mutex_a 保护变量a, 主线程加锁mutex_b,与此同时子线程先加锁mutex_b,再加锁mutex_a。两个线程僵持住。
程序执行卡住

root@ubuntu:/home/wy/network# ./a.out 
in parent thread, got mutex a, waiting for mutex b
in child thread, got mutex b, waiting for mutex a

2、线程和进程之间
子进程可能不清楚父进程继承而来的互斥锁的具体加锁/解锁状态。
在父进程中已经加锁了,子线程中再次加锁导致死锁。

#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <wait.h>

pthread_mutex_t mutex;

//线程中
void* another( void* arg )
{
    printf( "in child thread, lock the mutex\n" );
    pthread_mutex_lock( &mutex );
    sleep( 5 );
    pthread_mutex_unlock( &mutex );
}
int main()
{
    pthread_mutex_init( &mutex, NULL );
    pthread_t id;
    pthread_create( &id, NULL, another, NULL );
    sleep( 1 );
    int pid = fork();
    if( pid < 0 )
    {
        pthread_join( id, NULL );
        pthread_mutex_destroy( &mutex );
        return 1;
    }
    else if( pid == 0 )
    {
        printf( "I anm in the child, want to get the lock\n" );
        pthread_mutex_lock( &mutex );
        printf( "I can not run to here, oop...\n" );
        pthread_mutex_unlock( &mutex );
        exit( 0 );
    }
    else
    {
        pthread_mutex_unlock( &mutex );
        wait( NULL );
    }
    pthread_join( id, NULL );
    pthread_mutex_destroy( &mutex );
    return 0;
}

# ./a.out 
in child thread, lock the mutex
I anm in the child, want to get the lock
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

为了维护世界和平_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值