java多线程基础(五)

来源:互联网 发布:大数据魔镜破解版 编辑:程序博客网 时间:2024/06/05 16:20

java多线程基础(五)–回顾学习历程,由浅及深,作为个人笔记,也希望帮到需要的人
(3)Lock类
java并发包中存在Lock接口和它的实现类:ReentrantLock,ReentrantReadWriteLock.ReadLock和ReentrantReadWriteLock.WriteLock。功能与synchronized类似,但需要主动获取锁和释放锁,使用更灵活,并且可以使用中断或者超时获取锁,实现一些比较实用的同步特性。例如,synchronized同步锁获取之后,需要等待线程执行完成或者抛出异常JVM介入才会释放锁,在此之前其他线程只能等待,利用Lock类,则可以使用中断或者超时机制,避免线程无休止地等待下去。不过需要注意的是,使用Lock类主动获取锁之后需要主动释放锁,否则可能导致死锁现象,常见的处理是将unLock()放到finally块中,保证一定会执行。
Lock接口:

//Lock:lock();//最常用的获取锁的方法,最普通,如果锁已经被其他线程获取,则等待tryLock();//尝试获取锁,如果获取成功返回true,否则返回false,不管结果如何会立即返回tryLock(long time, TimeUnit unit);//尝试拿到锁,如果拿不到可以等待一段时间,拿到锁后返回true,可以响应中断lockInterruptibly();//获取锁,等待获取的时候可以响应中断,使用interrupt()中断等待

ReentrantLock是唯一一个实现了Lock接口的类,使用示例如下:

//以之前演示的PrintTask为例,加锁后效果同synchronized,其他几个方法使用时大同小异class PrintTask implements Runnable {    int count = 100;    Lock lock = new ReentrantLock();    @Override    public void run() {        while (true) {            lock.lock();            try {                printCount();            } catch (Exception e) {                e.printStackTrace();            } finally {                lock.unlock();            }           }    }    public void printCount() {        if (count > 0) {            try {                Thread.sleep(100);            } catch (InterruptedException e) {                e.printStackTrace();            }            System.out.println(Thread.currentThread().getName() + ": " + count--);        }    }}

ReadWriteLock接口:

//ReadWriteLock:Lock readLock();//获取读锁,可以分给多个线程,是多个线程可以同时进行读操作Lock writeLock();//获取写锁

ReentrantReadWriteLock实现了ReadWriteLock接口,使用示例如下:

//示例为写锁//可以发现,读锁可以有多个线程同时访问,而写锁只能一个线程在访问//加读锁执行效果同无synchronized,加写锁同synchronized。//不同之处在于,如果有线程获取了读锁,其他线程申请写锁需要等待;//反过来如果用线程获取了写锁,则其他线程获取读锁或者写锁都需要等待ReentrantReadWriteLock lock = new ReentrantReadWriteLock();    @Override    public void run() {        while (true) {            lock.writeLock().lock();            try {                printCount();            } catch (Exception e) {                e.printStackTrace();            } finally {                lock.writeLock().unlock();            }           }    }

Lock和synchronized的区别:
(1)Lock在JDK层面上实现,而同步锁是java的内置特性,在JVM层面实现
(2)Lock需要主动加锁和释放锁,发生异常是不会主动释放锁,可能导致死锁,而同步锁自动加锁和释放
(3)Lock使用某些方法可以响应中断,同步锁则会导致其他线程一直等待
(4)Lock可以读写分离,同时读


附录1:关于Lock的几个概念
可重入锁:获取锁之后执行内部代码再碰到新的锁,无锁再次申请,而是直接执行。Lock和synchronized均属于可重入锁
可中断锁:即可以用interrupt()中断等待获取锁的线程
公平锁/非公平锁:(是/否)按照请求顺序来获取锁
附录2:Java集合中线程安全的类
HashTable与HashMap实现的方法均一致,但HashTable都加锁了,所以是线程安全的;除此之外,vector,stack,enumeration也属于线程安全的类,需要注意的是线程安全的同时意味着效率低,应当慎重使用。而且线程安全只是说明内部方法提供的方法是线程安全的,如果联合操作,依然不是线程安全的。

0 0