zoukankan      html  css  js  c++  java
  • JDK 5.0 Concurrency Utilities 并发处理(1)ReentrantLock 可重入锁

    ReentrantLock -- 可重入的锁

    可重入锁指在同一个线程中,可以重入的锁。当然,当这个线程获得锁后,其他线程将等待这个锁被释放后,才可以获得这个锁。

    构造器:ReentrantLock(boolean fair): 布尔值用来表示,创建的这个锁是公平的锁,还是自由竞争的锁。所谓公平的锁,是指,各个希望获得所得线程获得锁的顺序是按到达的顺序获得,还是自由竞争获得。

    通常的使用方法:

    ReentrantLock lock = new ReentrantLock(); // not a fair lock

    lock.lock();

    try {

        // synchronized do something

    } finally {
        lock.unlock();
    }

    一个典型的例子:先测试可重入锁的重入特性,然后创建3个线程,每个线程启动后,尝试获取锁,获取锁后对共享数据 + 1,然后显示chula

    import java.util.Calendar;
    import java.util.concurrent.locks.ReentrantLock;

    public class TestLock {

     private ReentrantLock lock = null;

     // 用于线程同步访问的共享数据
     public int data = 100;
     
     public TestLock() {
      // 创建一个自由竞争的可重入锁
      lock = new ReentrantLock();
     }
     
     public static void main(String[] args) {
      
      TestLock tester = new TestLock();
      
      // 测试可重入,函数testReentry() 执行获取锁后,显示信息的功能
      tester.testReentry();
      // 能执行到这里而不阻塞,表示锁可重入
      tester.testReentry();
      // 再次重入
      tester.testReentry();
     
      // 释放重入测试的锁,要按重入的数量解锁,否则其他线程无法获取该锁。 
      tester.getLock().unlock();
      tester.getLock().unlock();
      tester.getLock().unlock();
      
      // 启动3个线程测试在锁保护下的共享数据data的访问
      tester.test();
     }
     
     public ReentrantLock getLock() {
      return lock;
     }
     
     public void test() {
      new Thread(new workerThread(this)).start();
      new Thread(new workerThread(this)).start();
      new Thread(new workerThread(this)).start();
     }
     
     public void testReentry() {
      lock.lock();
      
      Calendar now = Calendar.getInstance();
      
      System.out.println(now.getTime() + " " + Thread.currentThread() + " get lock.");
     }
     
     // 线程调用的方法
     public void testRun() throws Exception {
      // 加锁 
      lock.lock();
      
      Calendar now = Calendar.getInstance();

      try {
       // 获取锁后显示 当前时间 当前调用线程 共享数据的值(并使共享数据 + 1)
       System.out.println(now.getTime() + " " + Thread.currentThread() + " accesses the data " + data ++);
       
       // 模拟其他处理,这里假设休眠一下 
       Thread.sleep(500);
       
      } catch (Exception e) {
       e.printStackTrace();
      } finally {
       // 解锁 
       lock.unlock();
      }
     }
    }

    // 工作线程,调用TestServer.testRun
    class workerThread implements Runnable {
     
     private TestLock tester = null;
     
     public workerThread(TestLock testLock) {
      this.tester = testLock;
     }
     
     public void run() {
      // 循环调用,尝试加锁,并对共享数据+1,然后显示出来
      while (true) {
       try {
         // 调用tester.testRun()
         tester.testRun();
       } catch (Exception e) {
        e.printStackTrace();
       }
      }
     }
    }

    程序运行结果:

    Tue Jan 24 13:41:45 CST 2006 Thread[main,5,main] get lock.
    Tue Jan 24 13:41:46 CST 2006 Thread[main,5,main] get lock.
    Tue Jan 24 13:41:46 CST 2006 Thread[main,5,main] get lock.
    Tue Jan 24 13:41:46 CST 2006 Thread[Thread-0,5,main] accesses the data 100
    Tue Jan 24 13:41:46 CST 2006 Thread[Thread-1,5,main] accesses the data 101
    Tue Jan 24 13:41:47 CST 2006 Thread[Thread-2,5,main] accesses the data 102
    Tue Jan 24 13:41:47 CST 2006 Thread[Thread-2,5,main] accesses the data 103
    Tue Jan 24 13:41:48 CST 2006 Thread[Thread-2,5,main] accesses the data 104
    Tue Jan 24 13:41:48 CST 2006 Thread[Thread-0,5,main] accesses the data 105
    Tue Jan 24 13:41:49 CST 2006 Thread[Thread-0,5,main] accesses the data 106
    Tue Jan 24 13:41:49 CST 2006 Thread[Thread-0,5,main] accesses the data 107
    Tue Jan 24 13:41:50 CST 2006 Thread[Thread-0,5,main] accesses the data 108
    Tue Jan 24 13:41:50 CST 2006 Thread[Thread-1,5,main] accesses the data 109
    Tue Jan 24 13:41:51 CST 2006 Thread[Thread-1,5,main] accesses the data 110

    前三行表示main线程,重入3次获得该锁。
    第四行表示Thread-0线程,先获得锁,使共享数据+1,然后显示信息,然后释放锁。
    第五行表示Thread-1线程,获得锁,使共享数据+1,然后显示信息,然后释放锁。

    由程序输出的信息可以知道,各线程获得锁的顺序,是自由竞争的结果。
    如果将 lock = new ReentrantLock(); 改为:lock = new ReentrantLock(true);
    将看到如下的结果:

    Tue Jan 24 13:47:29 CST 2006 Thread[main,5,main] get lock.
    Tue Jan 24 13:47:30 CST 2006 Thread[main,5,main] get lock.
    Tue Jan 24 13:47:30 CST 2006 Thread[main,5,main] get lock.
    Tue Jan 24 13:47:30 CST 2006 Thread[Thread-0,5,main] accesses the data 100
    Tue Jan 24 13:47:30 CST 2006 Thread[Thread-1,5,main] accesses the data 101
    Tue Jan 24 13:47:31 CST 2006 Thread[Thread-2,5,main] accesses the data 102
    Tue Jan 24 13:47:31 CST 2006 Thread[Thread-0,5,main] accesses the data 103
    Tue Jan 24 13:47:32 CST 2006 Thread[Thread-1,5,main] accesses the data 104
    Tue Jan 24 13:47:32 CST 2006 Thread[Thread-2,5,main] accesses the data 105
    Tue Jan 24 13:47:33 CST 2006 Thread[Thread-0,5,main] accesses the data 106
    Tue Jan 24 13:47:33 CST 2006 Thread[Thread-1,5,main] accesses the data 107
    Tue Jan 24 13:47:34 CST 2006 Thread[Thread-2,5,main] accesses the data 108
    Tue Jan 24 13:47:34 CST 2006 Thread[Thread-0,5,main] accesses the data 109
    Tue Jan 24 13:47:35 CST 2006 Thread[Thread-1,5,main] accesses the data 110

    可以看到各线程获得锁的顺序,是按线程获得锁的顺序。
    (注: new Thread(new workerThread()).start(); 并不是表示线程启动的顺序,就是线程获得锁的顺序)

       

     

  • 相关阅读:
    sql server日志已满报错
    图片基础信息
    android小细节
    内存泄露分析
    一个非常快的android模拟器
    activity退出
    ListView中内容的动画效果
    视频相关android软件
    Android Screen Monitor抓取真机屏幕
    ListView中使用type需要注意的东西
  • 原文地址:https://www.cnblogs.com/kylindai/p/322557.html
Copyright © 2011-2022 走看看