Java编程思想里的小例子:使用显式的Lock对象,P679,第21.3.2小节,有一个文件AttemptLocking.java如下:
//: concurrency/AttemptLocking.java
// Locks in the concurrent library allow you
// to give up on trying to acquire a lock.
import java.util.concurrent.*;
import java.util.concurrent.locks.*;public class AttemptLocking {
  private ReentrantLock lock = new ReentrantLock();
  public void untimed() {
    boolean captured = lock.tryLock();
    try {
      System.out.println("tryLock(): " + captured);
    } finally {
      if(captured)
        lock.unlock();
    }
  }
  public void timed() {
    boolean captured = false;
    try {
      captured = lock.tryLock(2, TimeUnit.SECONDS);
    } catch(InterruptedException e) {
      throw new RuntimeException(e);
    }
    try {
      System.out.println("tryLock(2, TimeUnit.SECONDS): " +
        captured);
    } finally {
      if(captured)
        lock.unlock();
    }
  }
  public static void main(String[] args) {
    final AttemptLocking al = new AttemptLocking();
    al.untimed(); // True -- lock is available
    al.timed();   // True -- lock is available
    // Now create a separate task to grab the lock:
    new Thread() {
      { setDaemon(true); }
      public void run() {
        al.lock.lock();
        System.out.println("acquired");
      }
    }.start();
    Thread.yield(); // Give the 2nd task a chance
    al.untimed(); // False -- lock grabbed by task
    al.timed();   // False -- lock grabbed by task
  }
} /* Output:
tryLock(): true
tryLock(2, TimeUnit.SECONDS): true
acquired
tryLock(): false
tryLock(2, TimeUnit.SECONDS): false
*///:~有几点疑问:
1,我在运行这段代码的时候,很多时候结果不是给出的,而是
tryLock(): true
tryLock(2, TimeUnit.SECONDS): true
acquired
tryLock(): true
tryLock(2, TimeUnit.SECONDS): true
按照书里的说法,也就是说竞争到了锁,但得到这个结果的概率真的挺高的啊
2,但是按照书里的说法,untimed()方法如果拿不到这个锁的话就会继续等待,但怎么看出来的?看不出它哪里在等待啊?untimed()看起来并没有卡在拿锁这个问题上,后台线程不会自动释放锁,它还能返回false,之后timed()方法也返回false

解决方案 »

  1.   

    想法是没错的,但是有一点.
    new Thread() {
          { setDaemon(true); }
          public void run() {
            al.lock.lock();
            System.out.println("acquired");
          }
    }.start();
    谁能保证这个线程一定是在al.untimed(); // False -- lock grabbed by task
    al.timed();   // False -- lock grabbed by task这两句之前执行?要达到你的效果,你可能需要设置一个"屏障".这个屏障会阻止主线程的执行直到锁定线程执行完毕,即打印出"acquired"字符串后再执行主线程.例如,作如下修改.public static void main(String[] args) throws InterruptedException {
            final AttemptLocking al = new AttemptLocking();
            al.untimed(); // True -- lock is available
            al.timed();   // True -- lock is available
            // Now create a separate task to grab the lock:
            final CountDownLatch latch = new CountDownLatch(1);//1.增加一个"屏障"
            new Thread() {
                {
                    setDaemon(false);
                }            public void run() {
                    al.lock.lock();
                    System.out.println("acquired");
                    latch.countDown();//2.屏障解除
                }
            }.start();
            Thread.yield(); // Give the 2nd task a chance
            latch.await();//3.阻塞在屏障处直到屏障解除
            al.untimed(); // False -- lock grabbed by task
            al.timed();   // False -- lock grabbed by task
        }
    上面1,2,3处增加的代码就能保证线程的执行顺序了.
      

  2.   

    谢谢回答。不过之前可能没说清楚,我并不是想让它们按顺序执行。而是好奇为什么al.untimed()理应卡在拿锁这个问题上的时候,al.timed()为什么还能执行?
      

  3.   

    上面写错了.原因就是执行顺序的问题啊.
    lock.tryLock()这个方法不会阻塞的.不管拿没拿到锁,立即返回.
      

  4.   

    额,我再看了下trylock()的说明:If the lock is held by another thread then this method will return immediately with the value false.
    书上说,而不是等待至这个锁被释放,就像在untimed()方法中所看到的
    看来是我理解错了,是立即返回而不是等待。和synchronzied不同,synchronzied会一直等待,不过应该也有些处理方法可以让synchronzied等待特点时间后就放弃吧