当多个线程共享使用同一段内存时,为了保证数据的一致性,就需要考虑到线程同步的
问题。
互斥量(mutex)
保证同一时间只有一个线程访问数据,在线程访问数据前先对数据加锁,这样数据只能
为该线程所用,其他试图对数据加锁的线程将被阻塞直到当前线程释放对该数据的锁。
#include int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr); |
成功返回0,否则返回错误编号
pthread_mutex_t 是互斥量的数据类型。用它定义了一个互斥量之后还需要对互斥量作
初始化。初始化可直接赋值(如下),也可调用pthread_mutex_init来进行初始化。
pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t recmutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; pthread_mutex_t errchkmutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP; |
一个互斥量只有两个状态:unlocked(未上锁,不属于任一线程), locked(上锁,属于某
一线程)。一个互斥量不可能同时被两个不同的线程锁住。如果一个线程试图对某一互斥
量上锁,而该互斥量已为其他的线程锁住,则该线程会被阻塞直到该互斥量被释放。
pthread_mutex_init 用来初始化(mutex所指向的)互斥量,attr用来指定互斥量的属性。
如果不指定属性(attr为NULL),则使用默认的属性。
int pthread_mutex_lock(pthread_mutex_t *mutex); int pthread_mutex_unlock(pthread_mutex_t *mutex); int pthread_mutex_trylock(pthread_mutex_t *mutex); |
成功返回0,否则返回错误编号
pthread_mutex_lock用于对互斥量上锁。
如果该互斥量还未上锁,则对其上锁,且该互斥量就属于调用线程,
函数pthread_mutex_lock立即返回。
如果该互斥量已经为别的线程锁住,则pthread_mutex_lock阻塞调用线程,
直到该互斥量释放。
如果该互斥量已经被调用线程锁住,则调用线程再次用pthread_mutex_lock
该互斥量上锁时,处理过程与互斥量的类型有关。
fast - 调用线程阻塞,直到该锁释放。这样倒致调用线程死锁。 error checking - pthread_mutex_lock立即返回,错误码为EDEADLK。 recursive - pthread_mutex_lock 函数成功执行,且记录下调用线程对该互斥量上锁的次数。 这样的话,解锁时pthread_mutex_unlock调用的次数也必须一致,这样才能将锁置为unlocked状态。 |
pthread_mutex_trylock 与pthread_mutex_lock很相似,但是当互斥量已上锁时,此函数
并不阻塞调用线程,此时它只会立即返回并附带错误码EBUSY。
pthread_mutex_unlock 释放指定的互斥量。
如果互斥量的属性是
fast - 将其置于unlocked状态 recursive - 对一个互斥量有一个上锁的计数器,此时使该计数器减1, 当计数器减到0时 则释放该互斥量,变为unlocked状态。 error checking - |
int pthread_mutex_destroy(pthread_mutex_t *mutex);
成功返回0,否则返回错误编号
销毁一个互斥量对象,释放该互斥量的所持的一些资源。
//example: #include <stdio.h> #include <stdlib.h> #include <pthread.h> struct foo { int f_count; pthread_mutex_t f_lock; };
void err_sys(const char *s) { printf("%s\n", s); exit(-1); }
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); printf("foo_hold f_count = %d\n", fp->f_count); }
void foo_rele(struct foo *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);
printf(" foo_rele f_count = %d\n", fp->f_count); }
void * foo1(void *fp) { for (;;) foo_hold((struct foo *)fp); }
void * foo2(void *fp) { for (;;) foo_rele((struct foo *)fp); } int main(void) { int err; pthread_t tid1, tid2; struct foo *tt;
tt = foo_alloc();
err = pthread_create(&tid1, NULL, foo1, (struct foo *)tt); if (err != 0) err_sys("pthread_create error");
err = pthread_create(&tid2, NULL, foo2, (struct foo *)tt); if (err != 0) err_sys("pthread_create error");
err = pthread_join(tid1, NULL); if (err != 0) err_sys("pthread_join error");
err = pthread_join(tid2, NULL); if (err != 0) err_sys("pthread_join error");
printf("\n---------- over -------------\n");
exit(0); }
|
阅读(780) | 评论(1) | 转发(0) |