【JAVA多线程问题之死锁】
一、死锁是什么?
举个例子:两个人一起吃饭,每个人都拿了一只筷子,双方都在等待对方将筷子让给自己,结果两个人都吃不了饭。这种情况和计算机中的死锁情况很相似。
假设有两个线程,互相等待对方释放占有的锁,但是释放锁的条件又不可能形成,这时候死锁就形成了。
还是买票的问题,有的时候时会发生死锁的,将以前的代码改动一下,将会产生死锁:
/*
死锁的产生
*/
class Ticket implements Runnable
{
Object obj=new Object();
boolean flag;
private int sum=1000;
public void run()
{
if(flag==true)
{
while(true)
{
synchronized(obj)
{
//->Thread1
show();
}
}
}
else
{
while(true)
show();
}
}
public synchronized void show()
{
//->Thread0
synchronized(obj)
{
if(sum>0)
{
try
{
Thread.sleep(10);
}
catch (InterruptedException e)
{
}
System.out.println(Thread.currentThread().getName()+":function--"+sum--);
}
}
}
}
public class Demo
{
public static void main(String args[])
{
Ticket t=new Ticket();
t.flag=false;
Thread t1=new Thread(t);
Thread t2=new Thread(t);
t1.start(); try//加入等待时间,让线程0启动
{
Thread.sleep(10);
}
catch (InterruptedException e)
{ }
t.flag=true;
t2.start();
}
}
死锁的现象:
如图所示,光标停在下一行不断闪烁,没有任何输出。
死锁具体是怎么形成的?以上面的输出为例:
线程0启动之后,由于标志变量为false,所以走的是else块,进入死循环,调用show方法,拿到this锁,然后继续拿到obj锁,顺利执行完毕之后,依次释放obj锁、this锁,然后开始进行第二次循环,拿到了this锁,但是将要拿到obj锁的时候,CPU切换到了线程1,线程1启动之后,由于flag已经是true,所以走的是if块,拿到了obj锁,刚要拿this锁,CPU切换到了线程0,线程0已经拿到了this锁,所以开始请求obj锁,但是obj锁在线程1手里,所以CPU切换到了线程1;线程1已经拿到了obj锁,所以它开始请求this锁,但是this锁在线程0手里,于是CPU切换到了线程0;..................
我们经过上面的分析,由于两个线程手里各自拿着对方的锁,相互请求但是没有让其中一方先释放锁的条件,所以CPU在两个线程之间不断切换,但是不会执行任何一方的任务。
总结死锁产生的条件:
1.有两个或者两个以上的锁。
2.同步嵌套(锁的嵌套)
死锁代码简单实例1:
class Demo implements Runnable
{
boolean flag;
public Demo(){}
public Demo(boolean flag)
{
this.flag=flag;
}
public void run()
{
if(flag)
{
while(true)
{
synchronized(Sour.lock1)
{
System.out.println("if---------lock1-------");
synchronized(Sour.lock2)
{
System.out.println("if-------lock2------");
}
}
}
}
else
{
while(true)
{
synchronized(Sour.lock2)
{
System.out.println("else---------lock2-------");
synchronized(Sour.lock1)
{
System.out.println("else-------lock1------");
}
}
}
}
}
}
class Sour
{
public static final Object lock1=new Object();
public static final Object lock2=new Object();
}
public class DeadLockDemo
{
public static void main(String args[])
{
Demo d1=new Demo(true);
Demo d2=new Demo(false);
Thread t1=new Thread(d1);
Thread t2=new Thread(d2);
t1.start();
t2.start();
}
}
死锁代码简单实例二:
class Demo implements Runnable
{
boolean flag;
public Demo(){}
public Demo(boolean flag)
{
this.flag=flag;
}
public void run()
{
if(flag)
{
while(true)
{
synchronized(Sour.lock1)
{
System.out.println("if---------lock1-------");
synchronized(Sour.lock2)
{
System.out.println("if-------lock2------");
}
}
}
}
else
{
while(true)
{
synchronized(Sour.lock2)
{
System.out.println("else---------lock2-------");
synchronized(Sour.lock1)
{
System.out.println("else-------lock1------");
}
}
}
}
}
}
class Sour
{
public static final Object lock1=new Object();
public static final Object lock2=new Object();
}
public class DeadLockDemo
{
public static void main(String args[])
{
Demo d1=new Demo();
d1.flag=false;
//Demo d2=new Demo(false);
Thread t1=new Thread(d1);
Thread t2=new Thread(d1); t1.start();
try
{
Thread.sleep(10);
}
catch (InterruptedException e)
{
}
d1.flag=true;
t2.start();
}
}
可以观察发现两个代码基本相同,只是主函数中的方法略有不同,其中,第一个代码有99.9%的几率在第三行就锁上;第二个代码要到几百行才能锁上,甚至有时候锁不上。
第一种方法创建了两个实现了Runnable的接口对象,但是不影响结果;和第二个相比,第一个方法排除了不确定因素,是验证死锁程序的有效方法。
【JAVA多线程问题之死锁】的更多相关文章
- java多线程之 ---- 线程死锁
java多线程之线程死锁 产生死锁的主要原因: 由于系统资源不足. 进程执行推进的顺序不合适. 资源分配不当等. 假设系统资源充足.进程的资源请求都可以得到满足,死锁出现的可能性就非常低.否则就会因争 ...
- Java多线程——线程的死锁
Java多线程——线程的死锁 摘要:本文主要介绍了Java多线程中遇到的死锁问题. 部分内容来自以下博客: https://www.cnblogs.com/wy697495/p/9757982.htm ...
- Java多线程中的死锁
Java多线程中的死锁 死锁产生的原因 线程死锁是指由两个以上的线程互相持有对方所需要的资源,导致线程处于等待状态,无法往前执行. 当线程进入对象的synchronized代码块时,便占有了资源,直到 ...
- Java多线程中的死锁问题
Java程序基本都要涉及到多线程,而在多线程环境中不可避免的要遇到线程死锁的问题.Java不像数据库那么能够检测到死锁,然后进行处理,Java中的死锁问题,只能通过程序员自己写代码时避免引入死锁的可能 ...
- java多线程(八)-死锁问题和java多线程总结
为了防止对共享受限资源的争夺,我们可以通过synchronized等方式来加锁,这个时候该线程就处于阻塞状态,设想这样一种情况,线程A等着线程B完成后才能执行,而线程B又等着线程C,而线程C又等着线程 ...
- java 多线程争抢资源死锁
多线程争抢资源死锁的原理就是,A线程正在持有锁1却想获取锁2,B线程正在持有锁2却要获取锁1 代码如下: public class Main { static ReentrantLock lock1 ...
- java多线程中的死锁情况读书笔记
多线程中的死锁 在前面的分析中,我们知道一个对象可以用Synchronized方法或者其他的加锁形式来防止别的任务在互斥还没有释放的时候就访问这个对象. 试想一下这样的情况:某个任务在等待另一个任务, ...
- Java多线程7:死锁
前言 死锁单独写一篇文章是因为这是一个很严重的.必须要引起重视的问题.这不是夸大死锁的风险,尽管锁被持有的时间通常很短,但是作为商业产品的应用程序每天可能要执行数十亿次获取锁->释放锁的操作,只 ...
- Java多线程---------同步与死锁:synchronized;等待与唤醒:wait、notify、notifyAll;生命周期
1.问题的引出 class MyThread implements Runnable{ private int ticket = 5 ; // 假设一共有5张票 public void run(){ ...
- java多线程13 : 死锁
前言 死锁单独写一篇文章是因为这是一个很严重的.必须要引起重视的问题.这不是夸大死锁的风险,尽管锁被持有的时间通常很短,但是作为商业产品的应用程序每天可能要执行数十亿次获取锁->释放锁的操作,只 ...
随机推荐
- Caffe学习系列(10):命令行解析
训练网络命令: sudo sh ./build/tools/caffe train --solver=examples/mnist/train_lenet.sh 用预先训练好的权重来fine-tuni ...
- HDU 1503 带回朔路径的最长公共子串
http://acm.hdu.edu.cn/showproblem.php?pid=1503 这道题又WA了好几次 在裸最长公共子串基础上加了回溯功能,就是给三种状态各做一个 不同的标记.dp[n][ ...
- java socket client
用tornado做了个socket server.无奈联调的人员对接不上. 于是撸出了以下demo import java.io.*; import java.net.*; public class ...
- tornado 非阻塞方法
http://sebastiandahlgren.se/2014/06/27/running-a-method-as-a-background-thread-in-python/
- PHPCMS V9教程之快速入门
这篇文章要为大家来介绍PHPCMS V9这个系统的一些基本知识,PHPCMS是基于面向对象的,严格的安装MVC开发模式开发的CMS系统,同时他还是一个非 常不错的PHP框架.下面我们一起看一下PHPC ...
- Closest Binary Search Tree Value I & II
Closest Binary Search Tree Value Given a non-empty binary search tree and a target value, find the v ...
- js日期、月份:日期加一天等
// 日期,在原有日期基础上,增加days天数,默认增加1天 function addDate(date, days) { if (days == undefined || days == '') { ...
- shell脚本监控MySQL服务是否正常
监控MySQL服务是否正常,通常的思路为:检查3306端口是否启动,ps查看mysqld进程是否启动,命令行登录mysql执行语句返回结果,php或jsp程序检测(需要开发人员开发程序)等等: 方法1 ...
- 自定义循环滑动的viewpager
今天和大家分享一下如何定制一个可以循环滑动的viewpager.其实今天更重要的提供一种组件化思想,当然你可以理解为面向对象思想. 吐槽一下网上流行的实现方式吧(为了方便说明,下文称之为方式A),方式 ...
- Android实现Banner界面广告图片循环轮播(包括实现手动滑动循环)
前言:经常会看到有一些app的banner界面可以实现循环播放多个广告图片和手动滑动循环.本以为单纯的ViewPager就可以实现这些功能.但是蛋疼的事情来了,ViewPager并不支持循环翻页.所以 ...