Linux线程同步机制一--互斥锁mutex
2017-08-03 09:33
387 查看
一、互斥锁基本原理
互斥锁以排他方式防止共享数据被并发访问。互斥锁为一个二元变量,其状态分为开锁和上锁,将某个共享资源与某个特定互斥锁在逻辑上绑定(即要申请该资源必须先获取锁),对该共享资源的访问操作如下:1.在访问该资源前,首先申请该互斥锁,如果该互斥锁处于开锁状态,则申请到该锁对象,并占有该锁(使该锁处于锁定状态),以防止其他线程访问该资源;如果该锁处于锁定状态,默认阻塞当前线程。
2.只有锁定改互斥锁的进程才能释放该互斥锁,其他线程释放操作无效。
3.互斥锁的主要作用是保证线程执行完整性。
二、互斥锁操作流程
1.定义一个全局的锁;2.初始化锁;
3.创建线程;
4.上锁、操作公共资源、解锁;
5.线程退出,释放资源(销毁锁)。
三、互斥锁基本操作函数
互斥锁基本操作函数如下表所示:1.初始化互斥锁
在使用互斥锁前,需要定义互斥锁(全局变量),定义互斥锁的代码入下:
phtread_mutex_t lock;
初始化互斥锁的函数为
pthread_mutex_init,互斥锁函数声明如下:
/*Initialize a mutex*/ int pthread_mutex_init(pthread_mutex_t* mutex, pthread_mutexattr_t* mutexattr);
第1个参数mutex是指向要初始化的互斥锁的指针。
第2个参数mutexattr是指向属性对象的指针,该属性对象定义要初始化的互斥锁的属性。若该指针为NULL时,使用默认属性。
使用默认属性初始化互斥锁代码如下:
phtread_mutex_t mp; int ret = pthread_mutex_init(&mp, NULL);
使用自定义属性初始化互斥锁代码如下:
pthread_mutexattr_t mattr; phtread_mutex_t mp; int ret = pthread_mutex_init(&mp, &mattr);
pthread_mutex_init()函数返回值为0表示函数执行成功。否则,将返回错误编号以指明错误。
此外,还可以使用宏
PTHREAD_MUTEX_INITIALIZER初始化今天分配的互斥锁。此宏定义如下:
/*come from /usr/include/pthread.h*/ #define PTHREAD_MUTEX_INITIALIZER { { 0, } }
使用宏
PTHREAD_MUTEX_INITIALIZER初始化互斥锁代码如下:
phtread_mutex_t mp = PTHREAD_MUTEX_INITIALIZER;
2.申请互斥锁
如果一线程要占用一共享资源,必须先申请对应的互斥锁。
pthread_mutex_lock()函数以阻塞的方式申请互斥锁,其函数申明如下:
int pthread_mutex_lock(pthread_mutex_t* mutex);
pthread_mutex_trylock()函数以非阻塞方式申请互斥锁,函数申明如下:
int pthread_mutex_trylock(pthread_mutex_t* mutex);
pthread_mutex_lock()和
pthread_mutex_trylock()执行成功时返回0。否则,返回一个错误编号,以指明错误。
3.释放互斥锁
pthread_mutex_unlock()函数用来释放互斥锁,其函数申明如下:
/*Unlock a mutex*/ int pthread_mutex_unlock(pthread_mutex_t* mutex);
参数mutex为执行要解锁的互斥锁的指针。释放操作只能由占有该互斥锁的线程完成。该函数执行成功时返回0。否则,返回指明错误的错误编号(未设置errno变量)。
4.销毁互斥锁
pthread_mutex_destroy()函数用来释放互斥锁,其函数申明如下:
/*Destroy a mutex*/ int pthread_mutex_destroy(pthread_mutex_t* mutex);
参数mutex为执行要解锁的互斥锁的指针。该函数执行成功时返回0。否则,返回指明错误的错误编号。
四、示例
下面通过3个线程来计算1+2+3+…+100的值,代码如下:#include <stdio.h> #include <pthread.h> int sum = 0; void* pth_add1(void* arg) { int i; for (i=1; i<20; i++) { sum += i; usleep(10000); } pthread_exit(0); } void* pth_add2(void* arg) { int i; for (i=20; i<60; i++) { usleep(10000); sum += i; } pthread_exit(0); } void* pth_add3(void* arg) { int i; for (i=60; i<=100; i++) { sum += i; usleep(10000); } pthread_exit(0); } int main() { pthread_t tid1, tid2, tid3; int ret; ret = pthread_create(&tid1, NULL, pth_add1, NULL); if (0 != ret) { perror("create pthead error"); return -1; } ret = pthread_create(&tid2, NULL, pth_add2, NULL); if (0 != ret) { perror("create pthead error"); return -1; } ret = pthread_create(&tid3, NULL, pth_add3, NULL); if (0 != ret) { perror("create pthead error"); return -1; } pthread_join(tid1, NULL); pthread_join(tid2, NULL); pthread_join(tid3, NULL); printf("sum = %d\n", sum); return 0; }
运行结果如下所示:
由上图可知,四次运行结果中只有一次结果是对的,为什么会出现这样的情况呢?由于3个线程访问共享资源sum,而没有使用互斥锁导致,下面给每个线程加互斥锁:
#include <stdio.h> #include <pthread.h> pthread_mutex_t lock; int sum = 0; void* pth_add1(void* arg) { int i; // 申请互斥锁 pthread_mutex_lock(&lock); for (i=1; i<20; i++) { sum += i; usleep(10000); } // 释放互斥锁 pthread_mutex_unlock(&lock); pthread_exit(0); } void* pth_add2(void* arg) { int i; // 申请互斥锁 pthread_mutex_lock(&lock); for (i=20; i<60; i++) { usleep(10000); sum += i; } // 释放互斥锁 pthread_mutex_unlock(&lock); pthread_exit(0); } void* pth_add3(void* arg) { int i; // 申请互斥锁 pthread_mutex_lock(&lock); for (i=60; i<=100; i++) { sum += i; usleep(10000); } // 释放互斥锁 pthread_mutex_unlock(&lock); pthread_exit(0); } int main() { pthread_t tid1, tid2, tid3; int ret; // 初始化锁 pthread_mutex_init(&lock, NULL); ret = pthread_create(&tid1, NULL, pth_add1, NULL); if (0 != ret) { perror("create pthead error"); return -1; } ret = pthread_create(&tid2, NULL, pth_add2, NULL); if (0 != ret) { perror("create pthead error"); return -1; } ret = pthread_create(&tid3, NULL, pth_add3, NULL); if (0 != ret) { perror("create pthead error"); return -1; } pthread_join(tid1, NULL); pthread_join(tid2, NULL); pthread_join(tid3, NULL); // 销毁锁 pthread_mutex_destroy(&lock); printf("sum = %d\n", sum); return 0; }
运行结果如下:
由上图可知,4次运行结果均正确,这便证明互斥锁可以确保线程执行的完整性,故对共享资源的访问一定要用互斥锁保护起来。
相关文章推荐
- Linux3种线程同步机制的封装
- Linux线程编程 - 线程同步机制之信号量
- linux的线程同步机制
- linux 线程同步机制包装类
- Linux 线程同步机制:互斥、读写锁、条件变量
- Linux线程同步机制三--读写锁rwlock
- Linux线程同步机制-Futex(转)
- Linux中的线程同步机制(一) -- Futex引子
- Linux中的线程同步机制-futex
- Linux线程同步机制四--信号量sem
- Linux程序设计学习笔记----多线程编程线程同步机制之相互排斥量(锁)与读写锁
- Linux线程编程 - 线程同步机制之条件变量
- Linux线程同步机制的几种方法总结与对比
- Linux程序设计学习笔记----多线程编程线程同步机制之互斥量(锁)与读写锁
- Linux线程编程 - 线程同步机制之读写锁通信机制
- [Pthread] Linux中的线程同步机制(一) -- Futex
- linux的线程同步机制
- [Pthread] Linux中的线程同步机制(二)--In Glibc
- Linux线程同步机制二--条件变量cond
- [Pthread] Linux中的线程同步机制(三)--Practice