博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
linux网络编程----->线程死锁
阅读量:7300 次
发布时间:2019-06-30

本文共 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,如需转载请自行联系原作者

你可能感兴趣的文章
关于开发环境无法运行applet
查看>>
9 完整的用户注册登录实例
查看>>
1.AJAX简介
查看>>
MVC5-3 Result分析
查看>>
记SpannableString设多少span时注意事项
查看>>
iOS8.1 To iOS8.2
查看>>
C#中让窗体自动靠边隐藏
查看>>
多态基类的析构函数应该为虚函数
查看>>
数据结构之 循环表线性表
查看>>
python 实现进制转换(二进制转十进制)
查看>>
Scrum立会报告+燃尽图(十二月九日总第四十次):视频剪辑与用户反馈
查看>>
xlst
查看>>
修改PHP上传文件的大小限制(post)
查看>>
Tengine 添加第三方监控模块nginx-module-vts
查看>>
黑马程序员-面向对象-09天-4
查看>>
小强的HTML5移动开发之路(14)——Video标签详解
查看>>
大白话5分钟带你走进人工智能-第十八节逻辑回归之交叉熵损失函数梯度求解过程(3)...
查看>>
在wamp下安装bugfree
查看>>
《大道至简》第二章(是懒人创造了方法)读后感
查看>>
【database】database domain knowledge
查看>>