博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
线程死锁问题
阅读量:3943 次
发布时间:2019-05-24

本文共 3115 字,大约阅读时间需要 10 分钟。

线程死锁问题

一、什么是死锁?

举个例子来说明:早上起来两个男生上卫生间,其中男生A先跑去了卫生间,男生B拿到了卫生纸;然后男生A需要纸巾,男生B又需要卫生间,他们两个又不做出想让,都不想把自己的资源交给对方,那么就会在这里堵住,你等着我,我等着你。

在线程中,多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放,而该资源又被其他线程锁定,从而导致每一个线程都得等其它线程释放其锁定的资源,造成了所有线程都无法正常结束。这样的情况称为线程死锁

二、分析线程产生死锁的原因

  • 1.互斥使用: 当一个资源被一个线程占用,而别的线程不能使用的时候
  • 2.不可抢占: 该资源的使用是不能抢夺的,只能由持有该资源的线程主动释放该资源
  • 3.请求和保持: 就是当该线程去请求别的资源的时候,同时保持对原有资源的占有(不释放原有资源)
  • 4.循环等待: 即存在一个等待队列,比如:线程T1占由T2需要的资源,T2占有T3需要的资源,T3占有T1需要的资源。形成一个等待环路。

当这四个条件都满足的时候,就形成了死锁。如果打破其中任何一个条件,死锁就会消失。

三、模拟死锁

在我们现实开发中,嵌套的同步块或从其他调用一个同步方法或尝试锁定不同的对象,如果不是很小心就很有可能发生死锁

模拟死锁代码
public class ThreadDeadlock {
public static void main(String[] args) throws InterruptedException {
DeadLock deadLock = new DeadLock(false,"张三"); DeadLock deadLock1 = new DeadLock(true,"李四"); deadLock.start(); deadLock1.start(); }}class DeadLock extends Thread{
static Object obj1 = String.class; static Object obj2 = Integer.class; boolean flag; String name; DeadLock(boolean flag,String name){
this.flag=flag; this.name=name; } @Override public void run() {
try {
method(); } catch (InterruptedException e) {
e.printStackTrace(); } } public void method() throws InterruptedException {
if (flag){
synchronized (obj1){
System.out.println(this.name+"=========obj1"); Thread.sleep(1000); synchronized (obj2){
System.out.println(this.name+"=========obj2"); } } }else {
synchronized (obj2){
System.out.println(this.name+"=========obj2"); Thread.sleep(2000); synchronized (obj1){
System.out.println(this.name+"=========obj1"); } } } }}

结果:

在这里插入图片描述
我们看到张三在等obj1,而李四在等obj2,谁也不撒手自己的资源,所以就产生了死锁。
在这里插入图片描述

四、怎么解决死锁问题

方式一:将资源利用顺序一致

if (flag){
synchronized (obj1){
System.out.println(this.name+"=========obj1"); Thread.sleep(1000); synchronized (obj2){
System.out.println(this.name+"=========obj2"); } } }else {
synchronized (obj1){
System.out.println(this.name+"=========obj1"); Thread.sleep(2000); synchronized (obj2){
System.out.println(this.name+"=========obj2"); } } }

在这里插入图片描述

方式二:将嵌套的徒步代码块挪出来

if (flag){
synchronized (obj1){
System.out.println(this.name+"=========obj1"); Thread.sleep(1000); } synchronized (obj2){
System.out.println(this.name+"=========obj2"); } }else {
synchronized (obj2){
System.out.println(this.name+"=========obj2"); Thread.sleep(2000); synchronized (obj1){
System.out.println(this.name+"=========obj1"); } } }

在这里插入图片描述

转载地址:http://vtiwi.baihongyu.com/

你可能感兴趣的文章
增强 SSH 安全性的 7 条技巧
查看>>
this作用域、javascript面向…
查看>>
提高网页在IE和Firefox上的…
查看>>
提高网页在IE和Firefox上的…
查看>>
php的正则表达式 '/\b\w…
查看>>
ThinkPHP的标签制作及标签调用解析…
查看>>
Javascript的匿名函数与自执行
查看>>
jQuery.proxy()代理、回调方法
查看>>
php操作memcache的使用测试总结
查看>>
JS创建类和对象
查看>>
完整ASCII字符表(转)
查看>>
jquery事件重复绑定解决办法
查看>>
jQuery.extend 函数详解
查看>>
mysqli_query和mysql_query有何区…
查看>>
mysqli->multi_query()多条语句的…
查看>>
php引用(&)变量引用,函数引用,对…
查看>>
[转]yii执行流程(一 目录文…
查看>>
无需重启服务器让系统环境变量生效…
查看>>
配置CakePHP
查看>>
JQuery中$.ajax()方法参数详…
查看>>