ReentrantLock API

  java可重入锁,简单几个小案例,测试特性。

   1.尝试锁  tryLock

package com.cn.cfang.ReentrantLock;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Test02 {

    private Lock lock = new ReentrantLock();
    
    private void m1(){
        try{
            lock.lock();
            for(int i = 0; i < 10; i++){
                TimeUnit.SECONDS.sleep(1);
                System.out.println("m1() method " + i);
            }
        }catch(InterruptedException e){
            e.printStackTrace();
        }finally{
            lock.unlock();
        }
    }
    
    private void m2(){
        boolean isLocked = false;
        try {
            //尝试锁,如果已被其他线程锁住,无法获取锁标记,则返回false
            //相反,如果获取锁标记,则返回true
            //isLocked = lock.tryLock();
            
            //阻塞尝试锁:会阻塞参数代表的时长,再去尝试获取锁标记
            //如果超时未获取,不继续等待,直接返回false
            //阻塞尝试锁类似于自旋锁。
            isLocked = lock.tryLock(11, TimeUnit.SECONDS);
            if(isLocked){
                System.out.println("method m2 synchronized");
            }else{
                System.out.println("method m2 unsynchronized");
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            if(isLocked){
                lock.unlock();
            }
        }
    }
    
    public static void main(String[] args) {
        Test02 t = new Test02();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                t.m1();
            }
        }).start();
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(new Runnable() {
            @Override
            public void run() {
                t.m2();
            }
        }).start();
    }
}

  2. 可中断

package com.cn.cfang.ReentrantLock;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * ReentrantLock的可打断性
 * 
 * 打断 : 调用thread.interrupt()方法,可打断线程阻塞状态,抛出异常。
 * 可尝试打断,阻塞等待锁。
 * 
 * 阻塞状态 :包括普通阻塞状态,等待队列,锁池队列
 * 普通阻塞 : sleep,可以被打断。
 * 等待队列 : wait方法调用,也是一种阻塞状态,不能被打断,只能等待notify
 * 锁池队列 : 无法获取锁标记。不是所有的锁池队列都能被打断
 *         ReentrantLock的lock获取锁标记的时候,如果未获取,需要阻塞的去等待锁标记,无法被打断
 *         ReentrantLock的lockInterruptibly获取锁标记的时候,如果未获取,需要阻塞等待,可以被打断
 * 
 * @author cfang
 * 2018年5月4日 下午2:23:41
 */
public class Test03 {

    private Lock lock = new ReentrantLock();
    
    private void m1(){
        try {
            lock.lock();
            for(int i = 0; i < 5; i++){
                TimeUnit.SECONDS.sleep(1);
                System.out.println("m1() method " + i);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally{
            lock.unlock();
        }
    }
    
    private void m2(){
        try {
            lock.lockInterruptibly(); //可尝试打断,阻塞等待锁,可以被其他的线程打断阻塞状态
            System.out.println("m2() method");
        } catch (InterruptedException e) {
//            e.printStackTrace();
        }finally{
            //可能异常打断,所以释放锁标记必须进行异常处理
            try {
                lock.unlock();
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
    }
    
    public static void main(String[] args) {
        Test03 t = new Test03();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                t.m1();
            }
        }).start();
        
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                t.m2();
            }
        });
        t2.start();
        
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t2.interrupt(); //打断线程休眠阻塞等待。非正常结束阻塞状态的线程,都会抛出异常。
    }
}

  3. 公平锁 : ReentrantLock可定义公平锁,多个线程竞争锁标记的时候,公平锁会记录等待时长,当前线程执行结束后,会优先选取等待时长最长的线程,去获取锁标记执行。

    synchronized不具有此特性。

 1 package com.cn.cfang.ReentrantLock;
 2 
 3 import java.util.concurrent.TimeUnit;
 4 import java.util.concurrent.locks.Lock;
 5 import java.util.concurrent.locks.ReentrantLock;
 6 
 7 public class Test04 {
 8 
 9     public static void main(String[] args) {
10         TestReentrantlock t = new TestReentrantlock();
11         new Thread(t).start();
12         new Thread(t).start();
13     }
14     
15 }
16     
17 class TestReentrantlock implements Runnable{
18     
19     private Lock lock = new ReentrantLock(true); //加参数true,代表公平锁 
20     @Override
21     public void run() {
22         for (int i = 0; i < 5; i++) {
23             lock.lock();
24             try {
25                 System.out.println(Thread.currentThread().getName() + " get lock");
26             }finally{
27                 lock.unlock();
28             }
29         }
30     }
31 }

猜你喜欢

转载自www.cnblogs.com/eric-fang/p/8991208.html