我们将会使用两个工具同步线程:mutexes和condition variables。
线程的好处之一就是使用全局变量共享信息。当然,共享是要付出代价的,由此产生同步问题。
首先,如下代码:加入我们输入两个数字,10000000, 10000000,我们的期望值应该是两个数相加:20000000,但是实际结果当然不是,一般比20000000小。产生该结果的原因就是两个线程同时访问了全局变量。
static int glob = 0; void increment(int num){ int i ; printf("increment thread %d\n", num); for(i = 0; i < num; i++) glob++; } int main(int argc, char* argc[]){ pthread_t t1, t2; int s, num1, num2; void * res; scanf("%d %d",&num1, &num2); s = pthread_create(&t1, NULL, (void *)increment, (void *)num1); if(s != 0) printf("create1 failed\n"); s = pthread_create(&t2, NULL, (void *)increment, (void *)num2); if(s != 0) printf("create2 failed\n"); s = pthread_join(t1, NULL); s = pthread_join(t2, NULL); printf("glob = %d\n", glob); exit(0); }
如上图所示,两个线程串行访问,及给全局变量枷锁。
初始化锁的两种方式:动态初始化,静态初始化
静态初始化:pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
动态初始化:pthread_mutex_init(pthread_mutex_t *mtx, pthread_mutexaddr_t *attr);
动态初始化锁的几种情况:
1、为锁定义属性
2、mutex被动态的分配到堆内存中。
当使用完动态初始化的锁,我们要用pthread_mutex_destory(pthread_mutex_t * mutex);但必须保证,这个锁是解开的,而且没有其他线程要去锁定他。
初始化以后的锁是没有锁的,一下两个函数是对锁的操作。
int pthread_mutex_lock(pthread_mutex_t * mutex);
int pthread_mutex_lock(pthread_mutex_t * mutex);
#include"/home/ace/workspaces/linux-c/util.h" static int glob = 0; static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; void increment(int num){ int i, s; for(i = 0; i < num; i++){ s = pthread_mutex_lock(&mtx); if(s != 0) printf("pthread_mutex_lock\n"); glob++; s = pthread_mutex_unlock(&mtx); if(s != 0) printf("pthread_mutex_unlock\n"); } } int main(){ pthread_t t1, t2; void * res; int s, num1, num2; scanf("%d %d", &num1, &num2); s = pthread_create(&t1, NULL, (void *)increment, (void *) num1); if(s != 0) printf("thread %d down\n", num1); s = pthread_create(&t2, NULL, (void *)increment, (void *) num2); if(s != 0) printf("thread %d down\n", num2); s = pthread_join(t1, NULL); s = pthread_join(t2, NULL); printf("%d", glob); }
以上代码执行以后,得到预期结果。
如果当前的锁没有锁定,那么pthread_mutex_lock() 将会锁定,并马上返回执行下一条命令。
如果锁已经锁定那么pthread_mutex_lock()将会阻塞,直到锁被打开。