java多线程基础(五)

xiaoxiao2021-02-27  213

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也属于线程安全的类,需要注意的是线程安全的同时意味着效率低,应当慎重使用。而且线程安全只是说明内部方法提供的方法是线程安全的,如果联合操作,依然不是线程安全的。

转载请注明原文地址: https://www.6miu.com/read-11935.html

最新回复(0)