Linux线程同步之互斥体
在学习之前已经了解了基本框架,那么现在就来学习一下细节操作
mutex锁的类型
PTHREAD_MUTEX_NORMAL(普通锁)
普通锁是互斥体默认属性。该怎用怎么用
正常使用实例:
#include<stdio.h>
#include<pthread.h>
#include<errno.h>
#include<stdlib.h>
#include<stdbool.h>
pthread_mutex_t mymutex;
int global=0;
void *thread_test(void *param){
pthread_t threadID = pthread_self();
printf("pthread start ,threadID:%d\n" , threadID);
while(true){
pthread_mutex_lock(&mymutex);
printf("Mutex lock , global:%d\n" , global);
global++;
printf("Mutex unlock , global:%d\n" , global);
pthread_mutex_unlock(&mymutex);
sleep(1);
}
return NULL;
}
int main(int argc, const char *argv[])
{
int i;
pthread_mutexattr_t mutex_attr;
pthread_mutexattr_init(&mutex_attr);
pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_NORMAL);
pthread_mutex_init(&mymutex , &mutex_attr);
pthread_t threadID[5];
for( i =0 ; i < 5 ; i++ ){
pthread_create(&threadID[i] , NULL , thread_test , NULL);
}
for(i =0 ; i < 5 ; i++ ){
pthread_join(threadID[i] , NULL );
}
pthread_mutex_destroy(&mymutex );
pthread_mutexattr_destroy(&mutex_attr);
return 0;
}
加载打印:
线程加入锁以后会对全局变量进行很好的保护。我没每一次使用对全局变量自增操作以后,由于它不是原子性的操作,汇编代码进行了多部处理,就会导致数据发生错乱。
加入同步互斥锁机制以后,对全局变量数据很好的保护。
linux@linux:~/pthread$ ./a.out
pthread start ,threadID:-1252107456
Mutex lock , global:0
Mutex unlock , global:1
pthread start ,threadID:-1243714752
Mutex lock , global:1
Mutex unlock , global:2
pthread start ,threadID:-1226929344
Mutex lock , global:2
Mutex unlock , global:3
pthread start ,threadID:-1235322048
Mutex lock , global:3
Mutex unlock , global:4
pthread start ,threadID:-1218536640
Mutex lock , global:4
Mutex unlock , global:5
Mutex lock , global:5
Mutex unlock , global:6
Mutex lock , global:6
Mutex unlock , global:7
Mutex lock , global:7
Mutex unlock , global:8
Mutex lock , global:8
Mutex unlock , global:9
Mutex lock , global:9
Mutex unlock , global:10
Mutex lock , global:10
Mutex unlock , global:11
Mutex lock , global:11
Mutex unlock , global:12
Mutex lock , global:12
Mutex unlock , global:13
Mutex lock , global:13
Mutex unlock , global:14
Mutex lock , global:14
Mutex unlock , global:15
单线程双重锁:
int main(int argc, const char *argv[])
{
pthread_mutexattr_t mutex_attr;
pthread_mutexattr_init(&mutex_attr);
pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_NORMAL);
pthread_mutex_init(&mymutex , &mutex_attr);
int ret = pthread_mutex_lock(&mymutex);
printf("ret = %d\n" , ret);
ret = pthread_mutex_lock(&mymutex);
printf("ret = %d\n" , ret);
pthread_mutex_destroy(&mymutex );
pthread_mutexattr_destroy(&mutex_attr);
return 0;
}
调试:
发现程序被阻塞在了第一把锁上。如果将pthread_mutex_lock更换为trylock的话,会返回EBUSY=16错误码。
Starting program: /home/linux/pthread/a.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/i386-linux-gnu/libthread_db.so.1".
ret = 0
^C
Program received signal SIGINT, Interrupt.
0xb7fdd424 in __kernel_vsyscall ()
(gdb) bt
#0 0xb7fdd424 in __kernel_vsyscall ()
#1 0xb7fb79e2 in __lll_lock_wait () at ../nptl/sysdeps/unix/sysv/linux/i386/i686/../i486/lowlevellock.S:144
#2 0xb7fb3267 in _L_lock_847 () from /lib/i386-linux-gnu/libpthread.so.0
#3 0xb7fb30a0 in __GI___pthread_mutex_lock (mutex=0x804a044 <mymutex>) at ../nptl/pthread_mutex_lock.c:79
#4 0x0804873d in main (argc=1, argv=0xbffff144) at 4_pthread_mutex.c:55
PTHREAD_MUTEX_ERRORCHECK(检错锁)
使用lpthread_mutex_lock如果出错,会返回lEDEADLK = 35
不会出现阻塞。
linux@linux:~/pthread$ ./a.out
ret = 0
ret = 35
DEBUG:
单线程加两把锁
-----见上面的索引
多线程加锁
如果程序出问题,多把锁都去强一把锁,没有进行锁保护会出现什么情况?
预先肯定是会被锁定的,所以我们使用检错锁。
pthread start ,threadID:-1252385984
ret = 0, -1252385984
pthread start ,threadID:-1243993280
pthread start ,threadID:-1235600576
pthread start ,threadID:-1227207872
pthread start ,threadID:-1218815168
EDEADLK , -1252385984
EDEADLK , -1252385984
EDEADLK , -1252385984
PTHREAD_MUTEX_RECURSIVE(嵌套锁)
使用该属性,可以对一把锁进行多重上锁,但是如果想进行别的线程,就需要把家的n把锁都要解除掉.
如下程序,已经显示加了5把锁。
pthread start ,threadID:-1252951232
ret = 0, -1252951232
pthread start ,threadID:-1244558528
pthread start ,threadID:-1236165824
pthread start ,threadID:-1227773120
pthread start ,threadID:-1219380416
ret = 0, -1252951232
ret = 0, -1252951232
ret = 0, -1252951232
ret = 0, -1252951232