Linux 线程同步

线程同步

互斥锁

在线程实际运行过程中,我们经常需要多个线程保持同步。这时可以用互斥锁来完成任务(资源竞争)。可以通过使用pthread的互斥接口保护数据,在访问共享资源前对互斥量进行加锁,在访问完成后解开互斥量上的锁。

互斥量用pthread_mutex_t数据类型来表示,在使用互斥变量以前,必须先对其进行初始化,可以将其置为常量PTHREAD_MUTEX_INITIALIZER(只能用于静态分配的互斥量),也可以调用pthread_mutex_init函数进行初始化。若是动态的互斥量(如:调用malloc),就要在释放内存前先调用pthread_mutex_destroy函数。

#include

int pthread_mutex_init(pthread_mutex_t *restrict mutex,

const pthread_mutexattr_t *restrict attr);   //attr = NULL时,使用默认属性初始化互斥量

int pthread_mutex_destroy(pthread_mutex_t *mutex);


加锁和解锁

#include
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);

如果线程不希望被阻塞, 可以在线程中调用pthread_mutex_trylock函数对互斥量加锁。

unix环境高级编程的例子

//使用互斥锁保护数据结构
#include 
#include 
#include 
#include 
#include 

struct foo
{
	int f_count;
	pthread_mutex_t f_lock;
};

struct foo *foo_alloc(void)
{
	struct foo *fp;
	if((fp = malloc(sizeof(struct foo))) != NULL)
	{
		fp->f_count = 1;
		if(pthread_mutex_init(&fp->f_lock, NULL) != 0)
		{
			free(fp);
			return(NULL);
		}
	}
	return(fp);
}

void foo_hold(struct foo *fp)
{
	pthread_mutex_lock(&fp->f_lock);
	fp->f_count++;
	pthread_mutex_unlock(&fp->f_lock);
}

void foo_rele(struct fpp *fp)
{
	pthread_mutex_lock(&fp->f_lock);
	if(--fp->f_count == 0)
	{
		pthread_mutex_unlock(&fp->f_lock);
		pthread_mutex_destroy(&fp->f_lock);
		free(fp);
	}
	else
	{
		pthread_mutex_unlock(&fp->f_lock);
	}
}

避免死锁

如果线程试图对同一个互斥量加锁两次,那么它自身就会陷入死锁状态。当 需要 同时使用两个互斥锁时,总是让它们以相同的顺序加锁,以避免死锁,第二个互斥锁维护着一个用于跟踪foo数据结构的散列列表。这样hashlock互斥锁保护foo数据结构中的fh散列表和f_next散列链子段。foo结构中的f_lock互斥锁保护对foo结构中的其他字段的访问。

unix环境高级编程的例子

//使用两个互斥锁
#include 
#include 

#define NHASH 29
#define HASH(fp) (((unsigned long)fp) %NHASH)
struct foo *fh[NHASH];
pthread_muxtex_t hashlock = PTHREAD_MUTEX_INITIALIZER;

struct foo
{
	int f_count;
	pthread_mutex_t f_lock;
	struct foo *f_next;
	int f_id;
};

struct foo *foo_alloc(void)
{
	struct foo *fp;
	int idx;

	if((fp = malloc(sizeof(struct foo)))!= NULL)
	{
		fp->f_count = 1;
		if(pthread_mutex_init(&fp->f_lock, NULL) != 0)
		{
			free(fp);
			return(NULL);
		}
		idx = HASH(fp);
		pthread_mutex_lock(&hashlock);
		fp->f_next = fh[idx];
		fh[idx] = fp->f_next;
		pthread_mutex_lock(&fp->f_lock);
		pthread_mutex_unlock(&hashlock);
		pthread_mutex_unlock(&fp->f_lock);
	}
	rerutn(fp);
}

struct foo *foo_find(int id)
{
	struct foo *fp;
	int idx;

	idx = HASH(fp);
	pthread_mutex_lock(&hashlock);
	for(fp = fh[idx]; fp != NULL; fp = fp->f_next)
	{
		if(fp->f_id == id)
		{
			foo_hold(fd);
			break;
		}
	}
	pthread_mutex_unlock(&hashlock);
	return(fp);
}

void foo_rele(struct foo *fp)
{
	struct foo *tfp;
	int idx;

	pthread_mutex_lock(&fp->f_lock);
	if(fp->f_count == 1)
	{
		pthread_mutex_unlock(&fp->f_lock);
		pthread_mutex_lock(&hashlock);
		pthread_mutex_lock(&fp->f_lock);

		if(fp->f_count != 1)
		{
			fp->f_count--;
			pthread_mutex_unlock(&fp->f_lock);
			pthread_mutex_unlock(&hashlock);
			return;
		}
		idx = HASH(fp);
		tfp = fh[idx];
		if(tfp == fp)
		{
			fh[idx] = fp->f_next;
		}
		else
		{
			while(tfp->f_next != fp)
			{
				tfp = tfp->f_next;
			}
			tfp->f_next = fp->f_next;
		}

		pthread_mutex_unlock(&hashlock);
		pthread_mutex_unlock(&fp->f_lock);
		pthread_mutex_destroy(&fp->f_lock);
		free(fp);
	}
	else
	{
		fp->f_count--;
		pthread_mutex_unlock(&fp->f_lock);
	}
}



你可能感兴趣的:(Linux环境编程)