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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 赵永康 中级黑马   /  2012-9-23 23:05  /  1346 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

在看线程的时候突然看到了线程监听器的两种方法一个是用同步代码块synchronized 一个可以用Lock
突然一下子没明白Lock是怎么控制资源共享问题的???就是转不过弯来 求解

评分

参与人数 1技术分 +1 收起 理由
王德升 + 1 赞一个!

查看全部评分

4 个回复

倒序浏览
这是一个使用Lock在两个线程中访问资源A和B的例子
  1. import java.util.concurrent.locks.Lock;
  2. import java.util.concurrent.locks.ReentrantLock;

  3. class ThreadA extends Thread {
  4.         ReentrantLock lock1 = null;
  5.         ReentrantLock lock2 = null;

  6.         public ThreadA(ReentrantLock lock1, ReentrantLock lock2) {
  7.                 this.lock1 = lock1;
  8.                 this.lock2 = lock2;
  9.         }

  10.         @Override
  11.         public void run() {

  12.                 try {
  13.                         lock1.lock();
  14.                         System.out.println("ThreadA----获取资源A");
  15.                         sleep(3000);
  16.                         System.out.println("ThreadA----释放资源A");
  17.                 } catch (InterruptedException e) {
  18.                         e.printStackTrace();
  19.                 } finally {
  20.                         lock1.unlock();
  21.                 }

  22.                 try {
  23.                         lock2.lock();
  24.                         System.out.println("ThreadA----获取资源B");
  25.                         sleep(3000);
  26.                         System.out.println("ThreadA----释放资源B");
  27.                 } catch (InterruptedException e) {
  28.                         e.printStackTrace();
  29.                 } finally {
  30.                         lock2.unlock();
  31.                 }

  32.         }
  33. }

  34. class ThreadB extends Thread {
  35.         ReentrantLock lock1 = null;
  36.         ReentrantLock lock2 = null;

  37.         public ThreadB(ReentrantLock lock1, ReentrantLock lock2) {
  38.                 this.lock1 = lock1;
  39.                 this.lock2 = lock2;
  40.         }

  41.         @Override
  42.         public void run() {

  43.                 try {
  44.                         lock2.lock();
  45.                         System.out.println("ThreadB----获取资源B");
  46.                         sleep(3000);
  47.                         System.out.println("ThreadB----释放资源B");
  48.                 } catch (InterruptedException e) {
  49.                         e.printStackTrace();
  50.                 } finally {
  51.                         lock2.unlock();
  52.                 }
  53.                 try {
  54.                         lock1.lock();
  55.                         System.out.println("ThreadB----获取资源A");
  56.                         sleep(3000);
  57.                         System.out.println("ThreadB----释放资源A");
  58.                 } catch (InterruptedException e) {
  59.                         e.printStackTrace();
  60.                 } finally {
  61.                         lock1.unlock();
  62.                 }

  63.         }
  64. }

  65. public class LockDemo {
  66.         public static void main(String[] args) {
  67.                 ReentrantLock lock1 = new ReentrantLock(false);
  68.                 ReentrantLock lock2 = new ReentrantLock(false);
  69.                
  70.                 new ThreadA(lock1,lock2).start();
  71.                 new ThreadB(lock1,lock2).start();
  72.         }
  73. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
王德升 + 1 神马都是浮云

查看全部评分

回复 使用道具 举报
个人在学习线程过程中,对Lock的一点小结,希望对楼主有用:
多线程在JDK1.5版本升级时,推出一个接口Lock接口。

解决线程安全问题使用同步的形式。(同步代码块,要么同步函数)
其实最终使用的都是锁机制。

到了后期版本,直接将锁封装成了对象。
线程进入同步就是具备了锁,执行完,离开同步,就是释放了锁。

所以同步是隐士的锁操作,
而Lock对象是显示的锁操作。

它的出现就替代了同步。

要想实现生产一个才消费一个的效果,就需要用到等待唤醒机制。

在之前的版本中使用Object类中wait notify notifyAll的方式来完成的。
那是因为同步中的锁是任意对象,所以操作锁的等待唤醒的方法都定义在Object类中。

而现在锁是指定对象Lock。所以查找等待唤醒机制方式需要通过Lock接口来完成。

而Lock接口中并没有直接操作等待唤醒的方法,而是将这些方式又单独封装到了一个对象中。
这个对象就是Condition,将Object中的三个方法进行单独的封装。

并提供了功能一致的方法 await(),signal(),signalAll();

在来一个简单的等待/唤醒机制的例子:
class Res
{
        private String name;
        private int count;
        private boolean flag;
        private Lock lock = new ReentrantLock();//创建了一个锁对象。

        private Condition con = lock.newCondition();
       
        public  void set(String name)
        {
                lock.lock();//获取锁。
                try
                {
                        while(flag)
                                try{con.await();}catch(InterruptedException e){}
                        this.name = name+"---"+count;

                        count++;

                        System.out.println(Thread.currentThread().getName()+"...........生产者...."+this.name);
                        flag = true;
                        con.signalAll();
                }
                finally
                {
                        lock.unlock();//释放锁
                       
                }

        }

        public void get()
        {
                lock.lock();
                try
                {
                        while(!flag)
                                try{con.await();}catch(InterruptedException e){}

                        System.out.println(Thread.currentThread().getName()+"....消费者...."+this.name);
                        flag = false;
                        con.signalAll();
                       
                }
                finally
                {
                        lock.unlock();       
                }
               
        }
}

class Producer implements Runnable
{
        private Res r;
        Producer(Res r)
        {
                this.r = r;
        }
        public void run()
        {
                while(true)
                {
                        r.set("产品");
                }
        }
}

class Consumer implements Runnable
{
        private Res r;
        Consumer(Res r)
        {
                this.r = r;
        }
        public void run()
        {
                while(true)
                {
                        r.get();
                }
        }
}


class ProConDemo2
{
        public static void main(String[] args)
        {
                Res r = new Res();
                Producer pro = new Producer(r);
                Consumer con = new Consumer(r);

                Thread t0 = new Thread(pro);
                Thread t1 = new Thread(pro);
                Thread t2 = new Thread(con);
                Thread t3 = new Thread(con);

                t0.start();
                t1.start();
                t2.start();
                t3.start();
        }
}
回复 使用道具 举报
Lock
底层就是wait........ noity进行操作的 实行同步的

评分

参与人数 1技术分 +1 收起 理由
滔哥 + 1 参与有分

查看全部评分

回复 使用道具 举报
我的理解就是:Lock 的功能更为强大一些,毕竟是jdk1.5新出来的东西

比如 Lock 可以产生多个条件变量,可以实现多个类似于 wait, notifyAll 的等待及唤醒功能。
而 synchronized 只有一个条件变量,也就是锁对象的 wait 和 notifyAll毕竟
Lock 的锁定是通过代码实现的,而 synchronized 是在 JVM 层面上实现的
希望能对你理解有帮助

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马