ImageVerifierCode 换一换
格式:DOCX , 页数:15 ,大小:19.52KB ,
资源ID:26447476      下载积分:10 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/26447476.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(Java并发编程深入学习.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

Java并发编程深入学习.docx

1、Java并发编程深入学习Java并发编程深入学习Lock锁Lock锁介绍在Java 5.0之前,在协调对共享对象的访问时可以使用的机制只有synchronized和volatile。Java 5.0 增加了一种新的机制:ReentrantLock.它并不是一种替代内置加锁的方法,而是当内置加锁机制不适用时,作为一种可选择的高级功能。Lock接口Lock接口位于java.util.concurrent.locks包中,它定义了一组抽象的加锁操作。public interface Lock /获取锁 void lock(); / 如果当前线程未被中断,则获取锁 void lockInterrupt

2、ibly() throws InterruptedException; /仅在调用时锁为空闲状态才获取该锁/如果锁可用,则获取锁,并立即返回值 true。如果锁不可用,则此方法将立即返回值 false boolean tryLock(); /如果锁在给定的等待时间内空闲,并且当前线程未被中断,则获取锁 boolean tryLock(long time, TimeUnit unit) throws InterruptedException; /释放锁 void unlock(); /返回绑定到此 Lock 实例的新 Condition 实例 Condition newCondition();R

3、eetrantLock 实现了Lock接口,并提供了与synchronized相同的互斥性和内存可见性,在获取ReentrantLock时,有着与进入同步代码块相同的内存语义,在释放ReentrantLock时,同样有着与退出同步代码块相同的内存语义。lock锁与synchronized锁对比为什么要创建一种与内置锁如此相似的新加锁机制?在大多数情况下,内置锁都能很好地工作,但在功能上存在一些局限性。内置锁无法中断一个正在等待获取锁的线程,或者无法在请求获取一个锁时无限地等待下去。内置锁必须在获取该锁的代码块中释放,这虽然简化了编码工作,并且与异常处理操作实现了很好的交互,但却无法实现非阻塞结

4、构的加锁规则。所以需要一种更加灵活的加锁机制,lock锁便应运而生。Lock锁的标准使用形式如下:Lock lock = new ReentrantLock(); if (lock.tryLock() /尝试获取锁 try /更新对象状态 /捕获异常,并在必要时恢复不变性条件 finally lock.unlock();/注意要记得释放锁 else / 获取锁失败执行其他操作 如果没有使用finally来释放Lock,那么程序出错时,将很难追踪到最初发生错误的位置,因为没有记录应该释放锁的位置和时间。这一点也是ReetrantLock不能完全替代synchronized的原因,因为它更加危险,

5、程序并没有自动清除锁的机制,使用起来需要格外小心。锁的分类1.可重入锁当某一个线程请求一个由其他线程持有的锁时,发去请求的线程就会阻塞。由于内置锁可重入特性的存在,如果某个线程视图获得一个已经由它自己持有的锁,那么这个请求却会成功。如果锁具备可重入性,则称作为可重入锁。.像synchronized和ReentrantLock都是可重入锁,重入性表明了锁的分配机制:基于线程的分配,而不是基于方法调用的分配。重入锁的实现机制如下:为每个锁关联一个获取计数值和一个所有者线程。当计数器为0时这个锁被认为没有被任何线程持有。当线程请求一个未被持有的锁时,JVM将记下锁的持有者,并且将获取计数器置为1。如

6、果同一个线程再次获取这个锁,计数器将递增,而当线程退出同步代码块时,计数器会相应地递减。当计数器为0时,这个锁将被释放。可举个简单的例子,当一个线程执行到某个synchronized方法时,比如说method1,而在method1中会调用另外一个synchronized方法method2,此时线程不必重新去申请锁,而是可以直接执行方法method2。看下面这段代码就明白了:class MyClass public synchronized void method1() method2(); public synchronized void method2() 上述代码中的两个方法method1

7、和method2都用synchronized修饰了,假如某一时刻,线程A执行到了method1,此时线程A获取了这个对象的锁,而由于method2也是synchronized方法,假如synchronized不具备可重入性,此时线程A需要重新申请锁。但是这就会造成一个问题,因为线程A已经持有了该对象的锁,而又在申请获取该对象的锁,这样就会线程A一直等待永远不会获取到的锁。而由于synchronized和Lock都具备可重入性,所以不会发生上述现象。2.可中断锁可中断锁:顾名思义,就是可以相应中断的锁。在Java中,synchronized就不是可中断锁,而Lock是可中断锁。如果某一线程A正在

8、执行锁中的代码,另一线程B正在等待获取该锁,可能由于等待时间过长,线程B不想等待了,想先处理其他事情,我们可以让它中断自己或者在别的线程中中断它,这种就是可中断锁。下面的例子展示了中断锁的场景。public class TestLockInterrupt private static Lock lock = new ReentrantLock(); public static void main(String args) final TestLockInterrupt test = new TestLockInterrupt(); Thread ta = new Thread() Overri

9、de public void run() System.out.println(A线程启动了!-准备打印.); try test.print(A, aaaa); catch (InterruptedException e) System.out.println(A线程收到中断异常); ; Thread tb = new Thread() Override public void run() System.out.println(B线程启动了!-准备打印.); try test.print(B, bbbb); catch (InterruptedException e) System.out.p

10、rintln(B线程收到中断异常); ; ta.start(); tb.start(); try Thread.sleep(2000); catch (InterruptedException e) e.printStackTrace(); /判定Lock是否还被某个线程持有 if (ReentrantLock) lock).isLocked() System.out.println(等了两秒还没有获得锁,直接中断!); tb.interrupt(); public void print(String tName, String content) throws InterruptedExcep

11、tion lock.lockInterruptibly(); try /lock.lock(); System.out.println(线程 + tName + 获取锁并打印内容 + content); /模拟耗时操作,使某个线程能够在较长时间独占锁 Thread.currentThread().sleep(5000); /int i = 1; / while (i 准备打印.线程A获取锁并打印内容aaaaB线程启动了!-准备打印.等了两秒还没有获得锁,直接中断!B线程收到中断异常线程A释放了锁3.公平锁公平锁即尽量以请求锁的顺序来获取锁。比如同是有多个线程在等待一个锁,当这个锁被释放时,等待

12、时间最久的线程(最先请求的线程)会获得该锁,这种就是公平锁。非公平锁即无法保证锁的获取是按照请求锁的顺序进行的。这样就可能导致某个或者一些线程永远获取不到锁。在Java中,synchronized就是非公平锁,它无法保证等待的线程获取锁的顺序。而对于ReentrantLock和ReentrantReadWriteLock,它默认情况下是非公平锁,但是可以设置为公平锁。在ReentrantLock中定义了2个静态内部类,一个是NotFairSync,一个是FairSync,分别用来实现非公平锁和公平锁。这两个类的定义如下: /* * Sync object for non-fair locks

13、*/ static final class NonfairSync extends Sync private static final long serialVersionUID = 7316153563782823691L; /* * Performs lock. Try immediate barge, backing up to normal * acquire on failure. */ final void lock() if (compareAndSetState(0, 1) setExclusiveOwnerThread(Thread.currentThread(); else

14、 acquire(1); protected final boolean tryAcquire(int acquires) return nonfairTryAcquire(acquires); /* * Sync object for fair locks */ static final class FairSync extends Sync private static final long serialVersionUID = -3000897897090466540L; final void lock() acquire(1); /* * Fair version of tryAcqu

15、ire. Dont grant access unless * recursive call or no waiters or is first. */ protected final boolean tryAcquire(int acquires) final Thread current = Thread.currentThread(); int c = getState(); if (c = 0) if (!hasQueuedPredecessors() & compareAndSetState(0, acquires) setExclusiveOwnerThread(current);

16、 return true; else if (current = getExclusiveOwnerThread() int nextc = c + acquires; if (nextc 0) throw new Error(Maximum lock count exceeded); setState(nextc); return true; return false; 我们可以在创建ReentrantLock对象时,通过以下方式来设置锁的公平性:ReentrantLock lock = new ReentrantLock(true);1如果参数为true表示为公平锁,为fasle为非公平锁

17、。默认情况下,如果使用无参构造器,则是非公平锁。 其他常用方法另外在ReentrantLock类中定义了很多方法,比如:isFair() /判断锁是否是公平锁isLocked() /判断锁是否被任何线程获取了isHeldByCurrentThread() /判断锁是否被当前线程获取了hasQueuedThreads() /判断是否有线程在等待该锁在ReentrantReadWriteLock中也有类似的方法,同样也可以设置为公平锁和非公平锁。不过要记住,ReentrantReadWriteLock并未实现Lock接口,它实现的是ReadWriteLock接口。4.读写锁读写锁将对一个资源(比如

18、文件)的访问分成了2个锁,一个读锁和一个写锁。正因为有了读写锁,才使得多个线程之间的读操作不会发生冲突。ReadWriteLock就是读写锁,它是一个接口,ReentrantReadWriteLock实现了这个接口。这个接口定义如下: public interface ReadWriteLock /获取读锁 Lock readLock(); /获取写锁 Lock writeLock(); 下面的例子展示了读写锁的一些基本用法和特性。public class TestMain public static void main(String args) ReadWriteLock lock = ne

19、w ReentrantReadWriteLock(); final Lock readLock = lock.readLock(); final Lock writeLock = lock.writeLock(); final Resource resource = new Resource(); final Random random = new Random(); for (int i = 0; i 20; +i) /写线程 new Thread() public void run() writeLock.lock(); try resource.setValue(resource.get

20、Value() + 1); System.out.println(newSmpleDateFormat(yyyy-MM-dd HH:mm:ss.SSS).format(new Date() + - + Thread.currentThread() + 获取了写锁,修正数据为: + resource.getValue(); Thread.sleep(random.nextInt(1000);/随机休眠 catch (Exception e) e.printStackTrace(); finally writeLock.unlock(); .start(); for (int i = 0; i 2

21、0; +i) /读线程 new Thread() public void run() readLock.lock(); try System.out.println(newSimpleDateFormat(yyyy-MM-dd HH:mm:ss.SSS).format(new Date() + - + Thread.currentThread() + 获取了读锁,读取的数据为: + resource.getValue(); Thread.sleep(random.nextInt(1000);/随机休眠 catch (Exception e) e.printStackTrace(); final

22、ly readLock.unlock(); .start(); /资源类定义class Resource private int value; public void setValue(int value) this.value = value; public int getValue() return value; 运行结果2016-09-13 10:16:59.947 - ThreadThread-0,5,main获取了写锁,修正数据为:12016-09-13 10:17:00.829 - ThreadThread-1,5,main获取了写锁,修正数据为:22016-09-13 10:17

23、:01.502 - ThreadThread-2,5,main获取了写锁,修正数据为:32016-09-13 10:17:01.952 - ThreadThread-3,5,main获取了写锁,修正数据为:42016-09-13 10:17:02.641 - ThreadThread-4,5,main获取了写锁,修正数据为:52016-09-13 10:17:03.389 - ThreadThread-5,5,main获取了写锁,修正数据为:62016-09-13 10:17:04.380 - ThreadThread-6,5,main获取了写锁,修正数据为:72016-09-13 10:17

24、:05.377 - ThreadThread-7,5,main获取了写锁,修正数据为:82016-09-13 10:17:06.306 - ThreadThread-8,5,main获取了写锁,修正数据为:92016-09-13 10:17:06.470 - ThreadThread-9,5,main获取了写锁,修正数据为:102016-09-13 10:17:06.696 - ThreadThread-10,5,main获取了写锁,修正数据为:112016-09-13 10:17:06.911 - ThreadThread-11,5,main获取了写锁,修正数据为:122016-09-13

25、10:17:07.141 - ThreadThread-12,5,main获取了写锁,修正数据为:132016-09-13 10:17:07.170 - ThreadThread-13,5,main获取了写锁,修正数据为:142016-09-13 10:17:07.449 - ThreadThread-14,5,main获取了写锁,修正数据为:152016-09-13 10:17:07.939 - ThreadThread-15,5,main获取了写锁,修正数据为:162016-09-13 10:17:08.252 - ThreadThread-16,5,main获取了写锁,修正数据为:172

26、016-09-13 10:17:08.798 - ThreadThread-17,5,main获取了写锁,修正数据为:182016-09-13 10:17:09.119 - ThreadThread-18,5,main获取了写锁,修正数据为:192016-09-13 10:17:09.353 - ThreadThread-19,5,main获取了写锁,修正数据为:202016-09-13 10:17:10.336 - ThreadThread-20,5,main获取了读锁,读取的数据为:202016-09-13 10:17:10.336 - ThreadThread-21,5,main获取了读

27、锁,读取的数据为:202016-09-13 10:17:10.336 - ThreadThread-22,5,main获取了读锁,读取的数据为:202016-09-13 10:17:10.336 - ThreadThread-23,5,main获取了读锁,读取的数据为:202016-09-13 10:17:10.336 - ThreadThread-24,5,main获取了读锁,读取的数据为:202016-09-13 10:17:10.336 - ThreadThread-25,5,main获取了读锁,读取的数据为:202016-09-13 10:17:10.336 - ThreadThrea

28、d-26,5,main获取了读锁,读取的数据为:202016-09-13 10:17:10.336 - ThreadThread-27,5,main获取了读锁,读取的数据为:202016-09-13 10:17:10.337 - ThreadThread-28,5,main获取了读锁,读取的数据为:202016-09-13 10:17:10.337 - ThreadThread-29,5,main获取了读锁,读取的数据为:202016-09-13 10:17:10.337 - ThreadThread-30,5,main获取了读锁,读取的数据为:202016-09-13 10:17:10.33

29、7 - ThreadThread-31,5,main获取了读锁,读取的数据为:202016-09-13 10:17:10.337 - ThreadThread-32,5,main获取了读锁,读取的数据为:202016-09-13 10:17:10.337 - ThreadThread-33,5,main获取了读锁,读取的数据为:202016-09-13 10:17:10.338 - ThreadThread-34,5,main获取了读锁,读取的数据为:202016-09-13 10:17:10.338 - ThreadThread-35,5,main获取了读锁,读取的数据为:202016-09-13 10:17:10.338 - ThreadThread-36,5,main获取了读锁,读取的数据为:202016-09-13 10:17:10.338 - ThreadThread-37,5,main获取了读锁,读取的数据为:202016-09-13 10:17:10.

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1