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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 刘海源 中级黑马   /  2012-7-27 07:32  /  1254 人查看  /  1 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

线程里边同步synchronized锁和lock锁有啥区别了,企业了开发怎么用要具体点用代码的形式展示出来?

1 个回复

倒序浏览
本帖最后由 余清兰 于 2012-7-27 08:36 编辑

Synchronized关键字定义的有同步代码块和同步函数
Synchronized(对象)
{
    需要被同步的代码(操作的是共享数据的代码);
}
对象如同锁,持有锁的线程可以在同步中执行,没有持有锁的线程即使获取CPU的执行权,也进不去,因为没有获取锁。
任何对象都可作为锁,但只有同一个锁上的被等待线程,可以被同一个锁上的notify唤醒,不可以对不同锁中的线程进行唤醒。
同步函数的时候,非静态的函数的锁是this,静态的函数的锁是该类的字节码文件对象
当同步中嵌套同步,而锁却不同时,就会出现死锁。
具体的说:synchronized锁是隐式的锁,多线程时每次执行锁里的代码都要先进行判断锁是否释放,释放了才能持有锁,执行完代码后,就自动释放锁,加锁和释放锁都是隐式的
操作线程的wait()和notify()等方法都是继承的Object的,而且它要么用notify()唤醒线程池中的第一个被等待的线程,要么用notifyAll()唤醒所有被等待的线程,
它不能唤醒对方的线程:比如在多线程间通讯时,多个线程处理同一个资源,处理动作却不一样,要唤醒对方,可以创建多个Condition对象,用signal()方法来唤醒对方的等待线程。
JDK1.5中提供了多线程升级解决方案,将同步synchronized替换成显示lock操作(显示的锁机制)。将object中的wait,notify,notifyAll,替换成了Condition对象,
一个锁可以定义多个Condition对象,该对象可以Lock锁进行获取,可以实现本方只唤醒对方的等待线程。
下面用生产者和消费者的例子,分别用两种方式来体现,就可以看到区别了
  1. class res
  2. {
  3.         private String name;
  4.         private int count = 1;
  5.         private boolean flag = false;
  6.         public synchronized void set(String name)
  7.         {
  8.                 while(flag)
  9.                         try
  10.                         {
  11.                                 wait();
  12.                         }
  13.                         catch (Exception e)
  14.                         {
  15.                         }
  16.                 this.name=name+"=="+count++;
  17.                 System.out.println(Thread.currentThread().getName()+"生产者..."+this.name);
  18.                 flag = true;
  19.                 this.notifyAll();
  20.         }
  21.         public synchronized void out()
  22.         {
  23.                 while(!flag)
  24.                         try
  25.                         {
  26.                                 wait();
  27.                         }
  28.                         catch (Exception e)
  29.                         {
  30.                         }
  31.                 System.out.println(Thread.currentThread().getName()+"消费者........"+this.name);
  32.                 flag = false;
  33.                 this.notifyAll();
  34.         }
  35. }
  36. class Producer implements Runnable
  37. {
  38.         private res r;
  39.         Producer(res r)
  40.         {
  41.                 this.r = r;
  42.         }

  43.         public void run()
  44.         {
  45.                 while (true)
  46.                 {
  47.                         r.set("商品");
  48.                 }
  49.         }

  50. }
  51. class Consumer implements Runnable
  52. {
  53.         private res r;
  54.         Consumer(res r)
  55.         {
  56.                 this.r = r;
  57.         }
  58.         public void run()
  59.         {
  60.                 while (true)
  61.                 {
  62.                         r.out();
  63.                 }
  64.                
  65.         }


  66. }
  67. class resDemo
  68. {
  69.         public static void main(String[] args)
  70.         {
  71.                 res r = new res();
  72.                 Producer pro = new Producer(r);
  73.                 Producer pro1 = new Producer(r);
  74.                 Consumer con = new Consumer(r);
  75.                 Consumer con1 = new Consumer(r);

  76.                 Thread t1 = new Thread(pro);
  77.                 Thread t2 = new Thread(con);
  78.                 Thread t3 = new Thread(pro1);
  79.                 Thread t4 = new Thread(con1);
  80.                 t1.start();
  81.                 t2.start();
  82.                 t3.start();
  83.                 t4.start();
  84.         }
  85. }
复制代码
分析:当出现多个线程同时生产和消费时,为了避免重复生产同一个商品的情况,要用while循环,让每个线程获取执行权后都要判断标记flag,
为了避免所有线程都是等待状态,只能用notifyAll()唤醒所有线程池中的等待线程,若用notify容易出现只唤醒本方线程的情况,这样的话,若唤醒了本方线程,会出现全部等待情况,
若都唤醒了,那在消费者还没消费完商品的时候,有可能生产者的线程唤醒了又去判断锁,但又不能执行里面的代码(因为要等消费者消费完),每次判断锁都很消耗资源。
换成显示的锁后,就可以只唤醒对方的线程,就可以解决以上问题。
  1. import java.util.concurrent.locks.*;
  2. class res
  3. {
  4.         private String name;
  5.         private int count = 1;
  6.         private boolean flag = false;

  7.         private Lock lock = new ReentrantLock();
  8.         private Condition condition_pro = lock.newCondition();
  9.         private Condition condition_con = lock.newCondition();

  10.         public  void set(String name)throws InterruptedException
  11.         {
  12.                 lock.lock();
  13.                 try
  14.                 {
  15.                         while(flag)
  16.                         condition_pro.await();
  17.                         this.name=name+"=="+count++;
  18.                         System.out.println(Thread.currentThread().getName()+"生产者..."+this.name);
  19.                         flag = true;
  20.                         condition_con.signal();        
  21.                 }
  22.                 finally
  23.                 {
  24.                         lock.unlock();
  25.                 }
  26.         }
  27.         public  void out()throws InterruptedException
  28.         {
  29.                 lock.lock();
  30.                 try
  31.                 {
  32.                         while(!flag)
  33.                                 condition_con.await();
  34.                         System.out.println(Thread.currentThread().getName()+"消费者........"+this.name);
  35.                         flag = false;
  36.                         condition_pro.signal();
  37.                 }
  38.                 finally
  39.                 {
  40.                         lock.unlock();
  41.                 }
  42.                
  43.         }
  44. }
  45. class Producer implements Runnable
  46. {
  47.         private res r;
  48.         Producer(res r)
  49.         {
  50.                 this.r = r;
  51.         }

  52.         public void run()
  53.         {
  54.                 while (true)
  55.                 {
  56.                         try
  57.                         {
  58.                                 r.set("商品");
  59.                         }
  60.                         catch (InterruptedException e)
  61.                         {
  62.                         }
  63.                         
  64.                 }
  65.         }

  66. }
  67. class Consumer implements Runnable
  68. {
  69.         private res r;
  70.         Consumer(res r)
  71.         {
  72.                 this.r = r;
  73.         }
  74.         public void run()
  75.         {
  76.                 while (true)
  77.                 {
  78.                         try
  79.                         {
  80.                                 r.out();
  81.                         }
  82.                         catch (InterruptedException e)
  83.                         {
  84.                         }
  85.                         
  86.                 }
  87.                
  88.         }


  89. }
  90. class resDemo1
  91. {
  92.         public static void main(String[] args)
  93.         {
  94.                 res r = new res();
  95.                 Producer pro = new Producer(r);
  96.                 Producer pro1 = new Producer(r);
  97.                 Consumer con = new Consumer(r);
  98.                 Consumer con1 = new Consumer(r);

  99.                 Thread t1 = new Thread(pro);
  100.                 Thread t2 = new Thread(con);
  101.                 Thread t3 = new Thread(pro1);
  102.                 Thread t4 = new Thread(con1);
  103.                 t1.start();
  104.                 t2.start();
  105.                 t3.start();
  106.                 t4.start();
  107.         }
  108. }
复制代码
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马