天天看點

linux 互斥量

        互斥量從本質上講是一把鎖,在通路共享資源前對互斥量加鎖,在通路完成後釋放互斥量。對互斥量進行加鎖後,任何其他試圖再次對互斥量加鎖的線程都會被阻塞直到目前線程釋放該互斥鎖。如果釋放互斥量時有一個以上的線程阻塞,那麼所有該鎖上的阻塞線程都會變成可運作狀态,第一個變為運作的線程就可以對互斥量進行加鎖,其他線程就會看到互斥量依然是鎖着的,隻能再次等待該互斥量重新變成可有。在這種方式下,每次隻有一個線程可以向前執行。

       如果一個互斥鎖或者條件變量存放在多個程序間的共享的某個記憶體區中,那麼Posix還允許它用于程序間的同步。

       互斥鎖通常用于保護由多個線程或者多個程序分享的共享資料。

互斥量是用pthread_mutex_t資料類型表示的。

初始化及銷毀:

pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t  *restrictattr);

pthread_mutex_destroy(pthread_mutex_t  *mutex);
           

加鎖及解鎖:

pthread_mutex_lock(pthread_mutex_t  *mutex);

pthread_mutex_lock(pthread_mutex_t  *mutex);

pthread_mutex_unlock(pthread_mutex_t  *mutex);
           

一個demo:

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

//需要同步保護的結構體
struct foo 
{
	int f_cnt;
	pthread_mutex_t f_lock;
	int f_id;
	int f_data;
};

//alloct the obj
struct foo *foo_alloc(int id)
{
	struct foo *fp;

	if ((fp = malloc(sizeof(struct foo))) != NULL)
	{
		fp->f_cnt = 1;
		fp->f_id = id;
		if (pthread_mutex_init(&fp->f_lock, NULL) != 0)
		{
			free(fp);
			fp = NULL;
			return NULL;
		}
	}

	return fp;
}

//add a reference to the obj
void foo_hold(struct foo *fp)
{
	pthread_mutex_lock(&fp->f_lock);
	fp->f_cnt++;
	pthread_mutex_unlock(&fp->f_lock);
}

//release a reference to the obj
void foo_rele(struct foo *fp)
{
	pthread_mutex_lock(&fp->f_lock);
	if (--fp->f_cnt == 0)//last reference
	{
		pthread_mutex_unlock(&fp->f_lock);
		pthread_mutex_destroy(&fp->f_lock);
		free(fp);
	}
	else
	{
		pthread_mutex_unlock(&fp->f_lock);
	}
}

void *thread1(void *args)
{
	struct foo *fp = (struct foo*)args;
	while(fp->f_data <= 200)
	{
		foo_hold(fp);
		fp->f_data++;
		printf("thread1 f_data = %d\n", fp->f_data);
		foo_rele(fp);
		sleep(1);
	}
}

void *thread2(void *args)
{
	struct foo *fp = (struct foo*)args;
	while (fp->f_data <= 200)
	{
		foo_hold(fp);
		fp->f_data++;
		printf("thread2 f_data = %d\n", fp->f_data);
		foo_rele(fp);
		sleep(1);
	}
}

int main()
{
	pthread_t tid1, tid2;

	struct foo *fp = foo_alloc(1);

	pthread_create(&tid1, NULL, thread1, (void*)fp);
	pthread_create(&tid2, NULL, thread2, (void*)fp);

	pthread_join(tid1, NULL);

	exit(0);
}
           

繼續閱讀