继往开来 吐故纳新
日历
网志分类
· 所有网志 (990)
· 个人作品 (62)
· 软件设计 (33)
· 面向对象编程 (22)
· JavaAPI (39)
· Java开源工具 (31)
· Swing (34)
· Java语法细节 (39)
· 样式表CSS (12)
· XML (10)
· J2EE(JavaEE) (23)
· 算法数据结构 (64)
· 正则表达式 (4)
· 软件知识 (6)
· Java线程 (9)
· Web开发.Jsp/Servlet/Struts (20)
· 程序随想录 (7)
· Spring (5)
· Hibernate (7)
· J2SE 高级 (2)
· J2SE 高级 (0)
· Web开发.Ajax (16)
· Web开发.JavaScript (43)
· DB4O (2)
· Web开发.CSS/Html (22)
· C# (20)
· ERP (4)
· JDBC (1)
· 编程资源 (16)
· 编程感悟 (29)
· DB/Sql (13)
· VB (29)
· VC (2)
· 桌面脚本 (3)
· 新兴软件 (3)
· 英语学习 (21)
· 网文转载 (159)
· 职场风云 (39)
· 诗词歌赋 (32)
· 生活感言 (77)
· 奇文共赏 (13)
· 财经纵横 (6)
· 未分类 (11)
站内搜索
友情链接
· 歪酷博客
· 我的歪酷 非非共享界
· 偶要雷锋
· 豆瓣
· nczonline
· 当当网
· easyjf中文站
· Donews
· 天极Java文章列表
· W3CSchool
· taiten的BLOG
· Dojo中国
· Dojo
· Extjs.com
· Lifehack中文网志
· JaveEye的一个AS专题
· Banq's JDon
· Java 中文网址大全
· 梦想Java
· 360Doc个人图书馆
· java开源大全
· 我在硅谷动力的软件下载站
· 站长中国
· 随意贴
· CSS教学素材站
· java 参考中文站
· 面向构件与SOA社区
· 彩字生成
· 派派小说论坛
· 如坐春风
· 英语学习网
· BBC CHina
· www.dlbang.com
· 古文竖排格式在线转化工具
· 免费家谱
· 图片上传基地
· 风景壁纸
· 和风细雨
· MyC#BlogInCsdn

订阅 RSS

0203513

歪酷博客

开此博一为经验积累,二为资料收集,三为同道交流,四为资源共享.
« 上一篇: 【原创】线程的协调 下一篇: 【原创】线程的互斥 »
Junglesong @ 2008-04-05 14:43

本文内容

同步不是改善程序安全性的灵丹妙药。
发生死锁的两种情况和解决方法。

同步不是改善程序安全性的灵丹妙药

从《线程的同步》一节中我们可以知道,synchronized能保证只有一个线程进入同步方法或同步块,但为了安全性盲目给多线程程序加上synchronized关键字并不是问题解决之道,这不但会降低程序的效率;还有可能带来严重的问题-死锁。
死锁发生在两个或以上的线程在等待对象锁被释放,但程序的环境却让lock无法释放时。下面我们将看到两种类型的死锁例子。

某线程不退出同步函数造成的死锁

public class PaintBoard  extends Thread{
  private boolean flag=true;
 
  public void paint(){   
    System.out.println("模拟绘画");
  }
 
  public synchronized void run(){
    while(flag){
      try{
        paint();
        Thread.sleep(1000);
      }
      catch(InterruptedException ex){
        ex.printStackTrace();
      }
    }
  }
 
  public synchronized void stopDraw(){
    flag=false;
    System.out.println("禁止绘画");
  }
 
  public static void main(String[] args){
    PaintBoard paintBoard=new PaintBoard();
    paintBoard.start();
    new StopThread(paintBoard);
  }
}

public class StopThread implements Runnable{
  private PaintBoard paintBoard;
 
  public StopThread(PaintBoard paintBoard){
    this.paintBoard=paintBoard;
   
    Thread th=new Thread(this);
    th.start();
  }
 
  public void run(){
    while(true){
      System.out.println("试图停止绘画过程");
      paintBoard.stopDraw();
      System.out.println("停止绘画过程完成");
    }
  }
}

问题的发生和解决

刚才的死锁原因是run()函数中有一个无限循环,一个线程进入后会在其中往复操作,这使它永远不会放弃对this的锁定,结果导致其它线程无法获得this的锁定而进入stopDraw函数。
我们把修饰run函数的synchronized取消就能解决问题。 run函数中不会改变任何量,这种函数是不该加上synchronized的。

两个线程争抢资源造成的死锁.

public class Desk{
  private Object fork=new Object();
  private Object knife=new Object();
 
  public void eatForLeft(){
    synchronized(fork){
      System.out.println("左撇子拿起叉");
      sleep(1);
      synchronized(knife){
        System.out.println("左撇子拿起刀");
        System.out.println("左撇子开始吃饭");
      }
    }
  }
 
  public void eatForRight(){
    synchronized(knife){
      System.out.println("右撇子拿起刀");
      sleep(1);
      synchronized(fork){
        System.out.println("右撇子拿起叉");
        System.out.println("右撇子开始吃饭");
      }
    }
  }
 
  private void sleep(int second){
    try{
      Thread.sleep(second*1000);
    }
    catch(InterruptedException ex){
      ex.printStackTrace();
    }
  }
 
  public static void main(String[] args){
    Desk desk=new Desk();
    new LeftHand(desk);
    new RightHand(desk);
  }
}

public class LeftHand implements Runnable{
  private Desk desk;
 
  public LeftHand(Desk desk){
    this.desk=desk;
   
    Thread th=new Thread(this);
    th.start();
  }
 
  public void run(){
    while(true){
      desk.eatForLeft();
    }
  }
}

public class RightHand implements Runnable{
  private Desk desk;
 
  public RightHand(Desk desk){
    this.desk=desk;
   
    Thread th=new Thread(this);
    th.start();
  }
 
  public void run(){
    while(true){
      desk.eatForRight();
    }
  }
}

问题的发生和解决

这部分程序中于两个线程都要获得两个对象的锁定才能执行实质性操作,但运行起来却发现其它线程持有了自己需要的另一个锁定,于是停在Wait Set中等待对方释放这个锁定,结果造成了死锁。
解决这个问题的方法是保证锁对象的持有顺序,如果两个加上了同步的函数都是先刀后叉的形式则不会发生问题。

小结

同步不是改善程序安全性的灵丹妙药,盲目同步也会导致严重的问题-死锁.
某线程持续不退出同步函数会造成死锁.解决方法是去掉或更换不正确的同步。
两个线程都等待对方释放自己需要的资源也会造成死锁.这种情况的解决方法是确保同步锁对象的持有顺序。




评论 / 个人网页 / 扔小纸条
* 昵称

已经注册过? 请登录

新用户请先注册 以便能显示头像及追踪评论回复

Email
网址
* 评论
表情
 


 

分类小组论坛
杂谈 , 娱乐、八卦 , 文学、艺术 , 体育 , 旅游、同城 , 象牙塔 , 情感 , 时尚、生活 , 星座 , 科技

请注意遵守中华人民共和国法律法规, 如威胁到本站生存, 将依法向有关部门报告, 同时本站的相关记录可能成为对您不利的证据.

相关法律法规
全国人大常委会关于维护互联网安全的决定
中华人民共和国计算机信息系统安全保护条例
中华人民共和国计算机信息网络国际联网管理暂行规定
计算机信息网络国际联网安全保护管理办法
计算机信息系统国际联网保密管理规定