zoukankan      html  css  js  c++  java
  • JDK5.0 特性-线程锁Lock

    来自:http://www.cnblogs.com/taven/archive/2011/12/17/2291470.html

      1 import java.util.concurrent.ExecutorService;
      2 
      3 import java.util.concurrent.Executors;
      4 
      5 import java.util.concurrent.Future;
      6 
      7 import java.util.concurrent.locks.Lock;
      8 
      9 import java.util.concurrent.locks.ReadWriteLock;
     10 
     11 import java.util.concurrent.locks.ReentrantLock;
     12 
     13 import java.util.concurrent.locks.ReentrantReadWriteLock;
     14 
     15  
     16 
     17  
     18 
     19 /**
     20 
     21     在多线程编程里,一个重要的概念是锁定,如果一个资源是多个线程共享的,为了保证数据的完整性,在进行事务性操作时
     22 
     23 需要将共享资源锁定,这样可以保证只有一个线程能对资源进行操作,从而保证了数据的完整性.在J2SE5.0以前锁定的功能是
     24 
     25 由synchronized关键字来实现的.本节实例介绍如何使用J2SE 5.0中的新特性实现锁定,包括一般的锁、读写锁等.
     26 
     27 关键技术剖析:
     28 
     29     在J2SE5.0中的锁是由java.util.concurrent.locks.lock实现的,使用它的关键技术点如下:
     30 
     31     1.ReentrantLock类实现了Lock接口,通过它可以完全取代synchronized关键字.
     32 
     33     2.ReentrantLock的lock方法取得锁,如果该锁定没有被其他线程占据,则获取该锁定并返回,将保持计数器置为1;如果当前线程已经占据锁,则立即返回,将保持计数器加1;如果锁定被其他线程占据,则当前线程进入睡眠状态,等待其他线程释放
     34 
     35 锁,此时保持计数器置为1.
     36 
     37     3.ReentrantLock的unlock方法释放锁,如果当前线程是锁的占有者,则将保持计数器减1,如果保持计数器等于0,则释放锁.如果当前线程不是锁的占有者,则抛出异常.
     38 
     39     4.ReadWriteLock是一个继承Lock的接口,定义了读写锁.它的一个实现类是ReentrantReadWriteLock
     40 
     41     5.ReentrantReadWriteLock的writeLock方法获得用于写入操作的锁定,当获得写入锁时,其他线程想进行读写操作都必须等待.
     42 
     43     6.ReentrantReadWriteLock的readLock方法获得用于读操作的锁定,当获得读取锁时,其他读的线程可以继续获得读取锁,但是不能获得写入锁.   
     44 
     45 */
     46 
     47 public class Lockers {
     48 
     49        /**测试Lock的使用.在方法中使用Lock,可以避免使用synchronized关键字*/
     50 
     51        public static class LockTest{
     52 
     53               Lock lock = new ReentrantLock();//
     54 
     55               double value = 0d; //
     56 
     57               int addtimes = 0;
     58 
     59               /**
     60 
     61                * 增加value的值,该方法的操作分为2岁,而且相互依赖,必须实现在一个事务中
     62 
     63                * 所以该方法必须同步,以前的做法是在方法声明中使用synchronized关键字
     64 
     65                */
     66 
     67               public void addValue(double v){
     68 
     69                      lock.lock();//锁住锁
     70 
     71                      System.out.println("LockTest to addValue: " + v + " " + System.currentTimeMillis());
     72 
     73                      try {
     74 
     75                             Thread.sleep(1000);
     76 
     77                      }catch(InterruptedException e){
     78 
     79                      }
     80 
     81                      this.value += v;
     82 
     83                      this.addtimes++;
     84 
     85                      lock.unlock();
     86 
     87               }
     88 
     89               public double getValue(){
     90 
     91                      return this.value;
     92 
     93               }
     94 
     95        }
     96 
     97        public static void testLockTest() throws Exception{
     98 
     99               final LockTest lockTest = new LockTest();
    100 
    101               //新建任务1,调用lockTest的addValue方法
    102 
    103               Runnable task1 = new Runnable(){
    104 
    105                      public void run(){
    106 
    107                             lockTest.addValue(55.55);
    108 
    109                      }
    110 
    111               };
    112 
    113               //新建任务2,调用lockTest的getValue方法
    114 
    115                Runnable task2 = new Runnable(){
    116 
    117                       public void run(){
    118 
    119                              System.out.println("value: " + lockTest.getValue());
    120 
    121                       }
    122 
    123                };
    124 
    125                //新建任务执行服务
    126 
    127                ExecutorService cachedService = Executors.newCachedThreadPool();
    128 
    129                Future future = null;
    130 
    131                //同时执行任务1三次,由于 addValue方法使用了锁机制,所以,实质上会顺序执行
    132 
    133                for(int i=0;i<3;i++){
    134 
    135                       future = cachedService.submit(task1);
    136 
    137                }
    138 
    139                future.get();//等待最后一个任务1被执行完
    140 
    141                future = cachedService.submit(task2);//再执行任务2,输出结果
    142 
    143                future.get();//等待任务2执行完后,关闭任务执行服务
    144 
    145                cachedService.shutdownNow();
    146 
    147        }
    148 
    149        /**
    150 
    151         * ReadWriteLock内置两个Lock,一个是读的Lock,一个是写的Lock
    152 
    153         * 多个线程可同时得到读的Lock,但只有一个线程能得到写的Lock
    154 
    155         * 而且写的Lock被锁定后,任何线程都不能得到Lock.ReadWriteLock提供的方法有:
    156 
    157         * readLock():返回一个读的Lock
    158 
    159         * writeLock():返回一个写的lock,此lock是排它的
    160 
    161         * ReadWriteLockTest很适合处理类似文件的读写操作
    162 
    163         * 读的时候可以同时读,但是不能写,写的时候既不能同时写,也不能读
    164 
    165         */
    166 
    167        public static class ReadWriteLockTest{
    168 
    169               ReadWriteLock lock = new ReentrantReadWriteLock();//
    170 
    171               double value = 0d; //
    172 
    173               int addtimes = 0;
    174 
    175               /**增加value的值,不允许多个线程同时进入该方法*/
    176 
    177               public void addValue(double v){
    178 
    179                      //得到writeLock并锁定
    180 
    181                      Lock writeLock = lock.writeLock();
    182 
    183                      writeLock.lock();
    184 
    185                      System.out.println("ReadWriteLockTest to addValue: " + v + " " + System.currentTimeMillis());
    186 
    187                      try{
    188 
    189                             Thread.sleep(1000);
    190 
    191                      }catch(InterruptedException e){                        
    192 
    193                      }
    194 
    195                      try{
    196 
    197                             //做写的工作
    198 
    199                             this.value += v;
    200 
    201                             this.addtimes++;
    202 
    203                      }finally{
    204 
    205                             writeLock.unlock();
    206 
    207                      }
    208 
    209               }
    210 
    211               /**
    212 
    213                *获得信息.当有线程在调用addValue方法时,getInfo得到的信息可能是不正确的.
    214 
    215                *所以,也必须保证该方法在被调用时,没有方法在调用addValue方法.
    216 
    217                */
    218 
    219               public String getInfo(){
    220 
    221                      //得到 readLock并锁定
    222 
    223                      Lock readLock = lock.readLock();
    224 
    225                      readLock.lock();
    226 
    227                      System.out.println("ReadWriteLockTest to getInfo "+System.currentTimeMillis());
    228 
    229                      try{
    230 
    231                             Thread.sleep(1000);
    232 
    233                      }catch(InterruptedException e){
    234 
    235                      }
    236 
    237                      try{
    238 
    239                             return this.value + " : " + this.addtimes;//做读的工作
    240 
    241                      }finally{
    242 
    243                             readLock.unlock();//释放readLock
    244 
    245                      }
    246 
    247               }
    248 
    249        }
    250 
    251        public static void testReadWriteLockTest() throws Exception{
    252 
    253               final ReadWriteLockTest readWriteLockTest = new ReadWriteLockTest();
    254 
    255               //新建任务1,调用lockTest的addValue方法
    256 
    257               Runnable task_1 = new Runnable(){
    258 
    259                      public void run(){
    260 
    261                             readWriteLockTest.addValue(55.55);
    262 
    263                      }
    264 
    265               };
    266 
    267               //新建任务2,调用lockTest的getValue方法
    268 
    269               Runnable task_2 = new Runnable(){
    270 
    271                      public void run(){
    272 
    273                             System.out.println("info " + readWriteLockTest.getInfo());
    274 
    275                      }
    276 
    277               };
    278 
    279               //新建任务任务执行服务
    280 
    281               ExecutorService cachedService_1 = Executors.newCachedThreadPool();
    282 
    283               Future future_1 = null;
    284 
    285               //同时执行5个任务,其中前2个任务是任务1,后两个任务是任务2
    286 
    287               for(int i=0;i<2;i++){
    288 
    289                      future_1 = cachedService_1.submit(task_1);
    290 
    291               }
    292 
    293               for(int i=0;i<2;i++){
    294 
    295                      future_1 = cachedService_1.submit(task_2);
    296 
    297               }
    298 
    299               //最后一个任务是任务1
    300 
    301               future_1 = cachedService_1.submit(task_1);
    302 
    303               //这5个任务的执行顺序应该是
    304 
    305               //第一个任务1先执行,第二个任务1再执行;这是因为不能同时写,所以必须等
    306 
    307               //然后两个任务2同时执行;这是因为在写的时候,就不能读,所以都等待写结束
    308 
    309               //又同时可以同时读,所以它们同时执行
    310 
    311               //最后一个任务1再执行.这是因为在读的时候,也不能写,所以必须等待读结束后,
    312 
    313               //才能写.等待最后一个任务2被执行完
    314 
    315               future_1.get();
    316 
    317               cachedService_1.shutdownNow();
    318 
    319        }
    320 
    321        public static void main(String... args)throws Exception{
    322 
    323               Lockers.testLockTest();
    324 
    325               System.out.println("--------------------------");
    326 
    327               Lockers.testReadWriteLockTest();
    328 
    329        }
    330 
    331 }
    332 
    333 /**
    334 
    335  * ReentrantReadWriteLock  获取顺序如下:
    336 
    337  * This class does not impose a reader or writer preference ordering for lock access.
    338 
    339  * However, it does support an optional fairness policy.
    340 
    341  * When constructed as fair, threads contend for entry using an approximatelyarrival-order policy.
    342 
    343  * When the write lock is released either the longest-waiting single writer will beassigned the write lock, or if there is a reader waiting longer than any writer, theset of readers will be assigned the read lock.
    344 
    345  * When constructed as non-fair, the order of entry to the lock need not be in arrivalorder.
    346 
    347  * In either case, if readers are active and a writer enters the lock then nosubsequent readers will be granted the read lock until after that writer has acquiredand released the write lock.
    348 
    349 */
  • 相关阅读:
    CWMP开源代码研究6——libcwmp动态库开发
    CWMP开源代码研究5——CWMP程序设计思想
    CWMP开源代码研究4——认证流程
    CWMP开源代码研究2——easycwmp安装和学习
    CWMP开源代码研究3——ACS介绍
    CWMP开源代码研究1——开篇之作
    usb驱动开发之大结局
    usb驱动开发24之接口驱动
    usb驱动开发23之驱动生命线
    usb驱动开发22之驱动生命线
  • 原文地址:https://www.cnblogs.com/sunxucool/p/3842593.html
Copyright © 2011-2022 走看看