在多线程编程中, 为保证共享数据的完整性,引入互斥锁的概念,每个对象可以有一个mutex这样的标记,来标示这个对象在某一时刻只能被一个线程访问。
多线程程序一般使用互斥量来对临界区进行保护,临界区只允许加上互斥锁的那个线程来访问,其它的线程要等锁释放后重新加锁。
例如下面简单的程序,不加锁的情况下,任意线程都可以访问,导致a的值不可控制。
int get_a()
{
a++;
return a;
}
加锁之后,则同一时刻只会有一个线程访问。
int get_a()
{
lock(mutex);
a++;
unlock(mutex);
return a;
}
这个接口则是线程安全的。
另外互斥锁还分为几种类型
- 普通锁
- 嵌套锁
- 纠错锁
- 自适应锁
下面用两个例子来说明一下普通锁和纠错锁。
编程时一般约定某个线程加的锁只能由自身来释放,但是普通锁可以解别的线程加的锁。
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include<stdlib.h>
//静态方式创建
pthread_mutex_t tMutex = PTHREAD_MUTEX_INITIALIZER;
int count;
void *TdFunc(void *ptr)
{
pthread_t tid;
int i = *((int *)(ptr));
int ret = 0;
//获得线程自身的id
tid = pthread_self();
//将该线程的状态设为detached,则该线程运行结束后会释放所有资源。
pthread_detach(tid);
if (0 == i % 2) {
printf("%u try to lock mutex\n", tid);
ret = pthread_mutex_lock(&tMutex);
if (0 == ret) {
printf("%u lock mutex succ\n", tid);
} else {
printf("%u lock mutex failed\n", tid);
}
} else {
printf("%u try to unlock mutex\n", tid);
ret = pthread_mutex_unlock(&tMutex);
if (0 == ret) {
printf("%u try to unlock mutex succ\n", tid);
} else {
printf("%u unlock mutex failed\n", tid);
}
}
count++;
}
int main(int argc, char *argv[])
{
int i = 0;
int ret = 0;
//pthread不是linux系统默认的库,连接时需要使用静态库libthread.a
for (i = 0; i < atoi(argv[1]); ++i) {
pthread_t tid;
printf("%u\n", tid);
ret = pthread_create(&tid, NULL, TdFunc, &i);
if (0 != ret) {
strerror(ret);
return 0;
}
sleep(1);
}
while(count < 5);
return 0;
}