本文共 2777 字,大约阅读时间需要 9 分钟。
开发使用多线程过程中, 不可避免的会出现多个线程同时操作同一块共享资源, 当操作全部为读时, 不会出现未知结果, 一旦当某个线程操作中有写操作时, 就会出现数据不同步的事件.
而出现数据混乱的原因:
资源共享(独享资源则不会)
调试随机(对数据的访问会出现竞争)
线程间缺少必要的同步机制
以上三点, 前两点不能被改变. 欲提高效率, 传递数据, 资源必须共享. 只要资源共享, 就一定会出现线程间资源竞争, 只要存在竞争关系, 数据就会出现混乱.
所以只能从第三点着手, 使多个线程在访问共享资源的时候, 出现互斥.
线程同步:
指在一定的时间里只允许某一个进程访问某个资源,而在此时间内,不允许其它线程对该资源进行操作.
在使用锁的时候, 以下会出现死锁状态.
线程试图对一把锁进行加锁两次
哲学家就餐[N个哲学家, N支筷子, 哲学家同时对一个方向取筷子, 取到后需要拿另一方面的场子才可以就餐]
线程试图对一把锁进行加锁两次:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> /* * 模拟一个线程对一把锁进行加锁两次 * author sea time 2016/06/15 */ //创建一把互斥锁, 并进行静态初始化 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; //线程函数 void * thread_handler( void * args){ //第一次获取锁成功 pthread_mutex_lock(&mutex); //成功获取打印 printf ( "get mutex 1 successfully!\n" ); //第二次获取同一把锁 pthread_mutex_lock(&mutex); printf ( "get mutex 2 successfully!\n" ); pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex); pthread_exit(NULL); } int main( int argc, char * argv[]){ pthread_t tid; pthread_create(&tid, NULL, thread_handler, NULL); //等待线程结束 pthread_join(tid, NULL); //释放互斥锁 pthread_mutex_destroy(&mutex); return 0; } |
运行结果:
结果如预期所至, 一直阻塞在那获取锁.
哲学家就餐[N个哲学家, N支筷子, 哲学家同时对一个方向取筷子, 取到后需要拿另一方面的场子才可以就餐]:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> #include <string.h> /* * 模拟哲学家用餐模型 * author sea time 2016/0615 */ //用五把锁模拟五支筷子 pthread_mutex_t mutex[5]; void * thread_handler( void * args){ //获取当前位数 long i = ( long )args; int left, right; //当是最后一个哲学家 if ( sizeof (mutex)/ sizeof (*mutex) == i + 1){ left = i; right = 0; } else { left = i; right = i + 1; } //获取左边的筷子 pthread_mutex_lock(&mutex[left]); //等待100毫秒, 让其它线程都拿到自己右边的筷子 usleep(100); //获取右边的筷子 pthread_mutex_lock(&mutex[right]); sleep(2); printf ( "%ld 吃完了....!\n" , i); //解锁 pthread_mutex_unlock(&mutex[right]); //解锁 pthread_mutex_unlock(&mutex[left]); pthread_exit(NULL); } int main( int argc, char * argv[]){ long i = 0; int ret = 0; pthread_t tid[5]; //初始化五把锁 for (i = 0; i < sizeof (mutex)/ sizeof (*mutex); i++){ pthread_mutex_init(mutex+i, NULL); } //创建五个线程 for (i = 0; i < sizeof (tid)/ sizeof (*tid); i++){ pthread_create(tid+i, NULL, thread_handler, ( void *)i); } //等待线程 for (i = 0; i < sizeof (tid) / sizeof (*tid); i++){ pthread_join(tid[i], NULL); } //释放五把锁 for (i = 0; i < sizeof (mutex)/ sizeof (*mutex); i++){ pthread_mutex_destroy(mutex+i); } return ret; } |
运行结果: 会一直阻塞
结论: 在访问共享资源前加锁,访问结束后立即解锁。锁的“粒度”应越小越好。
本文转自asd1123509133 51CTO博客,原文链接:http://blog.51cto.com/lisea/1789733,如需转载请自行联系原作者