A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 黄玉昆 黑马帝   /  2013-3-23 20:43  /  1423 人查看  /  2 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 黄玉昆 于 2013-3-24 08:16 编辑

问题一:
在看完银行业务系统的视频后,自己在分析的时候,发现下面这句代码在三个方法中放在了不同的位置:
  1. Integer serviceNumber = NumberMachine.getInstance().getCommnManager().fetchServiceNumber();
复制代码
我想问的是,这句代码和下面两句代码互换位置有啥不一样呢?
  1. String windowName = "第" + number + "号" + type + "窗口";        
  2.                 System.out.println(windowName + "开始获取VIP任务!");                        
复制代码
问题二:
老师说上面serviceNumber这段代码和下面的不能用锁,否则会出现死锁,我想问的是,如果用Lock是不是也会出现死锁呢?

2 个回复

倒序浏览
本帖最后由 blackcaismine 于 2013-3-23 23:12 编辑

Integer serviceNumber = NumberMachine.getInstance().getCommnManager().fetchServiceNumber();中的fetchServiceNumber()方法是用于取出集合里的元素的,当集合里没有元素的话,那么这个方法就阻塞在那里,一直等到集合里有了新的数字之后才会继续执行,造成
String windowName = "第" + number + "号" + type + "窗口";      
                System.out.println(windowName + "开始获取VIP任务!");        
这段代码显示延迟。效果不好,老师是为了更好滴log效果才将这段println放在fetchServiceNumber()方法之上的。不然一下子跳出来一大堆
至于问题2
  1. import java.util.concurrent.locks.Lock;
  2. import java.util.concurrent.locks.ReentrantLock;
  3. public class kops
  4. {        
  5.         public static void main(String[] args)
  6.         {
  7.             Lock lock1 = new ReentrantLock();
  8.             Lock lock2 = new ReentrantLock();
  9.             new Thread(new kpwin(lock1,lock2,true)).start();
  10.             new Thread(new kpwin(lock1,lock2,false)).start();
  11.         }
  12. }
  13. class kpwin implements Runnable
  14. {
  15.     private Lock lock1 = null;
  16.     private Lock lock2 = null;
  17.     private boolean b;
  18.     kpwin(Lock lock1,Lock lock2,boolean b){
  19.         this.lock1=lock1;
  20.         this.lock2=lock2;
  21.         this.b=b;
  22.     }
  23.     public void run() {
  24.         // TODO Auto-generated method stub
  25.         while(true)
  26.         {
  27.             if(b)
  28.             {
  29.                 lock1.lock();
  30.                     System.out.println(Thread.currentThread().getName()+"进入锁1");
  31.                     try {
  32.                         Thread.sleep(100);
  33.                     } catch (InterruptedException e) {
  34.                         // TODO Auto-generated catch block
  35.                         e.printStackTrace();
  36.                     }
  37.                     lock2.lock();
  38.                         System.out.println(Thread.currentThread().getName()+"进入锁2");
  39.                     lock2.unlock();
  40.                 lock1.unlock();   
  41.             }else{
  42.                 lock2.lock();
  43.                     System.out.println(Thread.currentThread().getName()+"进入锁2");
  44.                     try {
  45.                         Thread.sleep(100);
  46.                     } catch (InterruptedException e) {
  47.                         // TODO Auto-generated catch block
  48.                         e.printStackTrace();
  49.                     }
  50.                     lock1.lock();
  51.                         System.out.println(Thread.currentThread().getName()+"进入锁1");
  52.                     lock1.unlock();
  53.                 lock2.unlock();   
  54.             }
  55.         }
  56.     }
  57. }


复制代码
我写了一段 验证了一下,
会嵌套死锁,和synchronized一样,只不过用法不太一样而已,lock对应unlock即可。

另外网上找的这俩区别,可供参考。我也趁机复习一下{:soso_e113:}
1、ReentrantLock 拥有Synchronized相同的并发性和内存语义,此外还多了 锁投票,定时锁等候和中断锁等候
     线程A和B都要获取对象O的锁定,假设A获取了对象O锁,B将等待A释放对O的锁定,
     如果使用 synchronized ,如果A不释放,B将一直等下去,不能被中断
     如果 使用ReentrantLock,如果A不释放,可以使B在等待了足够长的时间以后,中断等待,而干别的事情

    ReentrantLock获取锁定与三种方式:
    a)  lock(), 如果获取了锁立即返回,如果别的线程持有锁,当前线程则一直处于休眠状态,直到获取锁
    b) tryLock(), 如果获取了锁立即返回true,如果别的线程正持有锁,立即返回false;
    c)tryLock(long timeout,TimeUnit unit),   如果获取了锁定立即返回true,如果别的线程正持有锁,会等待参数给定的时间,在等待的过程中,如果获取了锁定,就返回true,如果等待超时,返回false;
    d) lockInterruptibly:如果获取了锁定立即返回,如果没有获取锁定,当前线程处于休眠状态,直到或者锁定,或者当前线程被别的线程中断

2、synchronized是在JVM层面上实现的,不但可以通过一些监控工具监控synchronized的锁定,而且在代码执行时出现异常,JVM会自动释放锁定,但是使用Lock则不行,lock是通过代码实现的,要保证锁定一定会被释放,就必须将unLock()放到finally{}中

3、在资源竞争不是很激烈的情况下,Synchronized的性能要优于ReetrantLock,但是在资源竞争很激烈的情况下,Synchronized的性能会下降几十倍,但是ReetrantLock的性能能维持常态;

评分

参与人数 1技术分 +2 收起 理由
黄玉昆 + 2 很给力!

查看全部评分

回复 使用道具 举报
blackcaismine 发表于 2013-3-23 22:32
Integer serviceNumber = NumberMachine.getInstance().getCommnManager().fetchServiceNumber();中的fetch ...

很感谢你的回答,我想应该会有更好地办法解决死锁的。我再多了解了解这方面的知识吧。感谢你
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马