1.对互斥锁初始化:
静态赋值法:
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_init函数初始化互斥锁:
int pthread_mutex_init(pthrad_mutex_t *mutex,const pthread_mutexattr_t *mutexattr);
mutexattr为互斥锁的属性。
3.解锁函数:
int pthread_mutex_unlock(pthread_mutex_t *mutex);用pthread_mutex_unlock函数解锁时,要满足两个条件:一是互斥锁必须处于加锁状态,二是调用本函数的线程必须是给互斥锁加锁的线程。解锁后如果其他线程在等待互斥锁,等待队列中第一个线程将获得互斥锁。
示例代码:
#include <pthread.h> #include <stdlib.h> #include <unistd.h> #include <stdio.h> int myglobal; void *thread_function(void *arg) { int i,j; for ( i=0; i<20; i++) { j=myglobal; j=j+1; printf("."); fflush(stdout); sleep(1); myglobal=j; } return NULL; } int main(void) { pthread_t mythread; int i; if ( pthread_create( &mythread, NULL, thread_function, NULL) ) { printf("error creating thread."); abort(); } for ( i=0; i<20; i++) { myglobal=myglobal+1; printf("o"); fflush(stdout); sleep(1); } if ( pthread_join ( mythread, NULL ) ) { printf("error joining thread."); abort(); } printf("\nmyglobal equals %d\n",myglobal); exit(0); }
pc@ubuntu:~/linux_lan/thread/lock$ ./thread1
o.o..o.o.o.o.o.o.o.o.o.o.o.o.o.oo.o.o.o.
myglobal equals 21
分析:
因为主线程和创建的线程都涉及对全局变量myglobal的操作,可以到主线程对全局变量myglobal进行20次加一操作,新线程也对全局变量myglobal进行了20次加一操作,但是返回时,全局变量myglobal为21。
首先在主线程进行了加一操作,sleep(1)时,开始执行新线程,新线程j是在原myglobal基础上加了1,但是没有赋值给myglobal之前,sleep(1),又开始执行主线程,myglobal加1,然后主线程sleep(1),此时myglobal=j,但是此时myglobal已经是加1后的了,所以myglobal值没有变。
现在看看加锁后,程序的运行结果:
#include<pthread.h> #include<stdlib.h> #include<unistd.h> #include<stdio.h> int myglobal; pthread_mutex_t mymutex=PTHREAD_MUTEX_INITIALIZER; void* thread_function(void*arg) { int i,j; for(i=0;i<20;i++) { pthread_mutex_lock(&mymutex); j=myglobal; j=j+1; printf("."); fflush(stdout); sleep(1); myglobal=j; pthread_mutex_unlock(&mymutex); } return NULL; } int main() { pthread_t mythread; int i; if(pthread_create(&mythread,NULL,thread_function,NULL)) { printf("error creating thread."); abort(); } for(i=0;i<20;i++) { pthread_mutex_lock(&mymutex); myglobal+=1; pthread_mutex_unlock(&mymutex); printf("o"); fflush(stdout); sleep(1); } if(pthread_join(mythread,NULL)) { printf("error joining thread."); abort(); } printf("\nmyglobal equal %d\n",myglobal); return 0; }
pc@ubuntu:~/linux_lan/thread/lock$ ./thread_lock
o....................ooooooooooooooooooo
myglobal equal 40
分析:
可以看到,在加锁的情况下,程序第一次执行新线程时,会一直执行下去,当新线程sleep(1)时,主线程试图加锁,但是因为新线程已经加锁,所以加锁一直失败,主线程处于阻塞状态,直到新线程执行完20此后,才该主线程执行,所以运行结果是40,即主线程与新线程分别对全局变量mygloabal加了20次。