线程同步-互斥量(mutex)
线程同步
多个线程同时访问共享数据时可能会冲突,于是需要实现线程同步。
一个线程冲突的示例
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#define Loop 1000000
//全局资然
int counter = 0;
void *fun(void *argv)
{
int i;
for (i = 0; i < Loop; i++)
{
counter++;
}
return (void *)0;
}
int main(void)
{
int i;
pthread_t pid[2];
for (i = 0; i < 10; i++)
{
counter = 0;
pthread_create(&pid[0], NULL, fun, NULL);
pthread_create(&pid[1], NULL, fun, NULL);
pthread_join(pid[0], NULL);
pthread_join(pid[1], NULL);
printf("counter=%d\n", counter);
}
return 0;
}
//$ ./a.out
//counter = 2000000
//counter = 2000000
//counter = 2000000
//counter = 2000000
//counter = 2000000
//counter = 2000000
//counter = 2000000
//counter = 2000000
//counter = 1919439
//counter = 2000000
如果Loop越大,想必结果不一样的可能性越大。
互斥量
互斥量(mutex)就是解决线程冲突的一种常见方法。
#include <pthread.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int pthread_mutex_destroy(pthread_mutex_t *mutex);
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
对以上代码加上互斥量
//mutex.c
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#define Loop 1000000
//初始化
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
//全局资然
int counter = 0;
void *fun(void *argv)
{
int i;
for (i = 0; i < Loop; i++)
{
pthread_mutex_lock(&m);
counter++;
pthread_mutex_unlock(&m);
}
return (void *)0;
}
int main(void)
{
int i;
pthread_t pid[2];
for (i = 0; i < 10; i++)
{
counter = 0;
pthread_create(&pid[0], NULL, fun, NULL);
pthread_create(&pid[1], NULL, fun, NULL);
pthread_join(pid[0], NULL);
pthread_join(pid[1], NULL);
printf("counter=%d\n", counter);
}
pthread_mutex_destroy(&m); //销毁互斥量
return 0;
}
只需在需要同步的代码块加上“锁”即可。
关键区
被互斥量锁住的代码块,称作关键区(Critical Section):保证在某一时刻只有一个线程能访问数据的简便办法。在任意时刻只允许一个线程对共享资源进行访问。如果有多个线程试图同时访问临界区,那么在有一个线程进入后其他所有试图访问此临界区的线程将被挂起,并一直持续到进入临界区的线程离开。临界区在被释放后,其他线程可以继续抢占,并以此达到用原子方式操作共享资源的目的。
关键区的范围,显然要尽可能的小。