初识Lock

初识Lock

从Java 5之后,在java.util.concurrent.locks包下提供了另外一种方式来实现同步访问,那就是Lock。synchronized是java中的一个关键字,也就是说是Java语言内置的特性。那么为什么会出现Lock呢?既然都可以通过synchronized来实现同步访问了,那么为什么还需要提供Lock?

这些问题就要从synchronized的弊端说起:
synchronized的一个缺点就是如果一个代码块被synchronized修饰了,当一个线程获取了对应的锁,并执行该代码块时,其他线程便只能一直等待,等待获取锁的线程释放锁。如果这个获取锁的线程由于要等待IO或者其他原因(比如调用sleep方法)被阻塞了,但是又没有释放锁,其他线程便只能干巴巴地等待,试想一下,这多么影响程序执行效率。
因此就需要有一种机制可以不让等待的线程一直无期限地等待下去(比如只等待一定的时间或者能够响应中断),通过Lock就可以办到。
还有很多地方Lock会比synchronized更有优势。可以通过具体学习去了解更多差别和优缺点。

总结:

  1. Lock不是Java语言内置的,synchronized是Java语言的关键字,因此是内置特性。Lock是一个类,通过这个类可以实现同步访问;
  2. Lock和synchronized有一点非常大的不同,采用synchronized不需要用户去手动释放锁,当synchronized方法或者synchronized代码块执行完之后,系统会自动让线程释放对锁的占用;而Lock则必须要用户去手动释放锁,如果没有主动释放锁,就有可能导致出现死锁现象。

注意一点,Lock是一个接口,只有一个实现类是ReentrantLock类,内部封装了更多的方法,可以查阅API文档学习。
Lock接口的方法:

public interface Lock {
    void lock();//获取锁
    void lockInterruptibly() throws InterruptedException;//
    boolean tryLock();
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
    void unlock();
    Condition newCondition();
}

初始学习Lock的lock()方法:
lock()方法是平常使用得最多的一个方法,就是用来获取锁。如果锁已被其他线程获取,则进行等待。
由于在前面讲到如果采用Lock,必须主动去释放锁,并且在发生异常时,不会自动释放锁。因此一般来说,使用Lock必须在try{}catch{}块中进行,并且将释放锁的操作放在finally块中进行,以保证锁一定被被释放,防止死锁的发生。通常使用Lock来进行同步的话,是以下面这种形式去使用的:

//优先实例化Lock对象
Lock lock = ...;
//对象获取锁
lock.lock();
try{
    //处理任务
}catch(Exception ex){
     
}finally{
//重中之重:释放锁
    lock.unlock();   //释放锁
}

具体实现的代码:

package Lock;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Lock其实是一个接口,在JDK1.5以后开始提供,其实现类常用的有ReentrantLock
 *
 * 这里所说的Lock对象即是只Lock接口的实现类,为了方便记忆或理解,都简称为Lock对象
 */
public class LockTest {
	
	List<Integer> al = new ArrayList<Integer>();
	Lock lock = new ReentrantLock();
	
	/**
	 * @param args
	 */
    public static void main(String[] args){
    	
    	LockTest lt = new LockTest();
    	
    	new Thread(){
    		public void run(){
    			this.setName("线程***1***");
    			lt.getMethod(Thread.currentThread());
    		}
    	}.start();
    	
    	new Thread(){
    		public void run(){
    			this.setName("线程+++2+++");
    			lt.getMethod(Thread.currentThread());
    		}
    	}.start();
    	
    }
    /**
     * 一个线程共同调用的方法
     * @param t
     */
    public void getMethod(Thread t){
    	
    	lock.lock();
    	
    	try {
	    	for(int i = 0;i < 5; i++){
	    		System.out.println(t.getName()+"正在添加"+i);
	    		al.add(i);
	    	}
	    	showList();
	    	System.out.println();
	    } finally {
    		
    		lock.unlock();
    	}
    } 
    
    public void showList(){
    	for (Integer i : al) {
			System.out.print(i+"\t");
		}
    }
}

/**
 * output
 * 线程***1***正在添加0
 *	线程***1***正在添加1
 * 线程***1***正在添加2
 * 线程***1***正在添加3
 * 线程***1***正在添加4
 * 0	1	2	3	4	
 * 线程+++2+++正在添加0
 * 线程+++2+++正在添加1
 * 线程+++2+++正在添加2
 * 线程+++2+++正在添加3
 * 线程+++2+++正在添加4
 * 0	1	2	3	4	0	1	2	3	4	
 */
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值