`
周凡杨
  • 浏览: 230122 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Lock详解 | Java并发编程

阅读更多

      在之前的多线程编程的文章中我们讲到了如何使用关键字synchronized加锁来实现同步访问。本文我们继续来探讨锁这个问题,从Java 5之后,在java.util.concurrent.locks包下提供了另外一种锁的方式来实现同步访问,那就是Lock。


      既然都可以通过synchronized锁来实现同步访问了,那么为什么Java还提供java.util.concurrent.locks包来实现锁的机制? 即生瑜,何生亮?


这里就不得不罗列一下synchronized的不足之处:使用synchronized关键字会锁住某一段程序,别的程序如果需要调用的话就必须等待,这样减少了速度、效率。并发的情况下有可能产生死锁,导致程序中断。而且对多线程环境中,使用synchronized后,线程要么获得锁,执行相应的代码,要么无法获得锁处于等待状态,对于锁的处理不灵活。而Lock提供了多种基于锁的处理机制,比如:

  • lockInterruptibly() 如果当前线程未被中断,则获取锁。
  • tryLock() 仅在调用时锁为空闲状态才获取该锁。
  • unlock() 释放锁。

多线程竞争一个锁(synchronized锁)时,其余未得到锁的线程只能不停的尝试获得锁,而不能中断。高并发的情况下会导致性能下降。ReentrantLock的 lockInterruptibly()方法可以优先考虑响应中断。 一个线程等待时间过长,它可以中断自己,然后ReentrantLock响应这个中断,不再让这个线程继续等待。有了这个机制,使用 ReentrantLock时就不会像synchronized那样产生死锁了。

 

一:关于java.util.concurrent.locks

 

查看JDK源码,先了解一下locks包下都有哪些class文件,大致熟悉下包里文件的个数、文件名

 


 

查看包文件后,接下来就要查看每一个文件,进行分类,哪些class文件是interface类型,哪些是class类型,以及接口与实现类之间的对应关系。

整理包下的类关系图为:

 


 

说明:

 

  •  其中类ReadLockWriteLock的代码是位于ReentrantReadWriteLock.java文件里,且有加public static关键字进行修饰。
  • 其中类ReentrantLock.java的文件里还含有:SyncNonfairSyncFairSync三个静态类。其中Sync extends AbstractQueuedSynchronizer
 

二:Lock源码

 

package java.util.concurrent.locks;
import java.util.concurrent.TimeUnit;

/**
 * {@code Lock} implementations provide more extensive locking
 * operations than can be obtained using {@code synchronized} methods
 * and statements.  They allow more flexible structuring, may have
 * quite different properties, and may support multiple associated
 * {@link Condition} objects.
 */
public interface Lock {

    /**
     * Acquires the lock.
     */
    void lock();

    /**
     * Acquires the lock unless the current thread is
     * {@linkplain Thread#interrupt interrupted}.
     */
    void lockInterruptibly() throws InterruptedException;

    /**
     * Acquires the lock only if it is free at the time of invocation.
     */
    boolean tryLock();

    /**
     * Acquires the lock if it is free within the given waiting time and the
     * current thread has not been {@linkplain Thread#interrupt interrupted}.
     */
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;

    /**
     * Releases the lock.
     */
    void unlock();

    /**
     * Returns a new {@link Condition} instance that is bound to this
     * {@code Lock} instance.
     *
     */
    Condition newCondition();
}

 

说明

  • lock()tryLock()tryLock(long time, TimeUnit unit)lockInterruptibly()是用来获取锁的。

  • unLock()方法是用来释放锁的。
  • newCondition()用于线程协作。
 

三:Lock的使用

   用一个简单的例子来看看Lock是怎么用的

   

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

import org.apache.commons.lang.math.RandomUtils;

public class LockDemo {

	Lock lock = new ReentrantLock(); 
	
	public static void main(String[] args){
		final LockDemo d = new LockDemo(); 
		new Thread(){
			@Override
			public void run(){
				d.insert(Thread.currentThread());
			}
		}.start();
		new Thread(){
			@Override
			public void run(){
				d.insert(Thread.currentThread());
			}
		}.start();
	}
	
	public void insert(Thread thread){
		//加锁
		lock.lock();
		
		try{
			System.out.println(thread.getName()+"获得了锁");
			
			// TODO 做些事情吧...
			
			Thread.sleep(RandomUtils.nextInt(100));
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			//释放锁
			lock.unlock();
			System.out.println(thread.getName()+"释放了锁");
		}
	}
}

    

运行结果

Thread-0获得了锁

Thread-0释放了锁

Thread-1获得了锁

Thread-1释放了锁

 

说明:申请锁是通过Lock lock = new ReentrantLock();语句实现的。在数据同步代码块里,先通过lock.lock();语句进行加锁,在退出数据同步代码块时通过lock.unlock();释放锁。需要注意的是lock.unlock()是放在finally语句里的,即这个语句的执行很重要!

 

 

 

参考资料:

     https://www.ibm.com/developerworks/cn/java/j-jtp10264/

http://www.cnblogs.com/dolphin0520/p/3923167.html

http://blog.csdn.net/aesop_wubo/article/details/7544148

http://www.blogjava.net/BucketLi/archive/2010/09/30/333471.html

http://blog.csdn.net/chy996633/article/details/8627903

 

 

 

 

  • 大小: 11.8 KB
  • 大小: 50.1 KB
1
1
分享到:
评论

相关推荐

    Java 并发核心编程

    本文的主题是关于具有java语言风格的Thread、synchronized、volatile,以及J2SE5中新增的概念,如锁(Lock)、原子性(Atomics)、并发集合类、线程协作摘要、Executors。开发者通过这些基础的接口可以构建高并发、线程...

    龙果 java并发编程原理实战

    龙果 java并发编程原理实战 第2节理解多线程与并发的之间的联系与区别 [免费观看] 00:11:59分钟 | 第3节解析多线程与多进程的联系以及上下文切换所导致资源浪费问题 [免费观看] 00:13:03分钟 | 第4节学习并发的四...

    Java并发编程原理与实战

    并发工具类CountDownLatch详解.mp4 并发工具类CyclicBarrier 详解.mp4 并发工具类Semaphore详解.mp4 并发工具类Exchanger详解.mp4 CountDownLatch,CyclicBarrier,Semaphore源码解析.mp4 提前完成任务之FutureTask...

    龙果java并发编程完整视频

    第37节并发工具类CountDownLatch详解00:22:04分钟 | 第38节并发工具类CyclicBarrier 详解00:11:52分钟 | 第39节并发工具类Semaphore详解00:17:27分钟 | 第40节并发工具类Exchanger详解00:13:47分钟 | 第41节...

    汪文君高并发编程实战视频资源下载.txt

    │ Java并发编程.png │ ppt+源码.rar │ 高并发编程第二阶段01讲、课程大纲及主要内容介绍.wmv │ 高并发编程第二阶段02讲、介绍四种Singleton方式的优缺点在多线程情况下.wmv │ 高并发编程第二阶段03讲、...

    Java 并发编程原理与实战视频

    java并发编程原理实战 第2节理解多线程与并发的之间的联系与区别 [免费观看] 00:11:59分钟 | 第3节解析多线程与多进程的联系以及上下文切换所导致资源浪费问题 [免费观看] 00:13:03分钟 | 第4节学习并发的四个...

    java并发编程

    第38节并发工具类CyclicBarrier 详解00:11:52分钟 | 第39节并发工具类Semaphore详解00:17:27分钟 | 第40节并发工具类Exchanger详解00:13:47分钟 | 第41节CountDownLatch,CyclicBarrier,Semaphore源码解析00:29:57...

    汪文君高并发编程实战视频资源全集

    │ Java并发编程.png │ ppt+源码.rar │ 高并发编程第二阶段01讲、课程大纲及主要内容介绍.wmv │ 高并发编程第二阶段02讲、介绍四种Singleton方式的优缺点在多线程情况下.wmv │ 高并发编程第二阶段03讲、...

    Java高并发编程详解:多线程与架构设计 (Java核心技术系列)

    第三部分详细、深入地介绍volatile关键字的语义,volatile关键字在Java中非常重要,可以说它奠定了Java核心并发包的高效运行,在这一部分中,我们通过实例展示了如何使用volatile关键字以及非常详细地介绍了Java内存...

    并发编程之synchronized&Lock&AQS详解(1)1

    一、同步省略 二、将堆分配转化为栈分配 三、分离对象或标量替换

    【2018最新最详细】并发多线程教程

    1.并发编程的优缺点 2.线程的状态转换以及基本操作 3.java内存模型以及happens-before规则 4.彻底理解synchronized 5.彻底理解volatile 6.你以为你真的了解final吗? 7.三大性质总结:原子性、可见性以及有序性 8....

    JAVA核心知识点整理(有效)

    25 JAVA8 与元数据.................................................................................................................................25 2.4. 垃圾回收与算法 .................................

    java面试题,180多页,绝对良心制作,欢迎点评,涵盖各种知识点,排版优美,阅读舒心

    【多线程】简述synchronized 和java.util.concurrent.locks.Lock的异同? 90 【线程】ThreadLocal的作用 90 【Spring】什么是IOC和DI?DI是如何实现的 91 【Spring】spring中的IOC(控制反转)的原理 92 【Spring】...

    Linux多线程服务端编程:使用muduo C++网络库

    《Linux多线程服务端编程:使用muduo C++网络库》主要讲述采用现代C++在x86-64 Linux上编写多线程TCP网络服务程序的主流常规技术,重点讲解一种适应性较强的多线程服务器的编程模型,即one loop per thread。...

Global site tag (gtag.js) - Google Analytics