java并发的处理方式.doc_第1页
java并发的处理方式.doc_第2页
java并发的处理方式.doc_第3页
java并发的处理方式.doc_第4页
java并发的处理方式.doc_第5页
免费预览已结束,剩余8页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、java 并发的处理方式1 什么是并发问题。 多个进程或线程同时(或着说在同一段时间内 )访问同一资源会产生并发问题。银行两操作员同时操作同一账户就是典型的例子。比如 A、 B 操作员同时读取一余额为 1000 元的账户, A 操作员为该账户增加 100 元,B 操作员同时为该账户减去50 元,A先提交,B后提交。 最后实际账户余额为1000-50=950元,但本该为1000+100-50=1050。这就是典型的并发问题。如何解决?可以用锁。用法1public class Testpublic synchronized void print().;某线程执行print() 方法,则该对象将加锁

2、。其它线程将无法执行该对象的所有synchronized块。用法2public classTestpublic void print()synchronized(this)/锁住本对象.;同用法 1, 但更能体现synchronized用法的本质。用法3public class Testprivate String a = test;public void print()synchronized(a)/锁住 a 对象.;public synchronized void t().; / 这个同步代码块不会因为print()而锁定.执行 print() ,会给对象 a 加锁,注意不是给Test 的

3、对象加锁,也就是说Test 对象的其它synchronized方法不会因为print() 而被锁。同步代码块执行完,则释放对a 的锁。为了锁住一个对象的代码块而不影响该对象其它synchronized块的高性能写法:public class Testprivate byte lock = new byte0;public void print()synchronized(lock).;public synchronized void t().;静态方法的锁public class Testpublic synchronized static void execute().;效果同 public

4、 class Testpublic static void execute()synchronized(TestThread.class).;3 Java 中的锁与排队上厕所。锁就是阻止其它进程或线程进行资源访问的一种方式,即锁住的资源不能被其它请求访问。在 JAVA 中,sychronized关键字用来对一个对象加锁。比如 :public class MyStack int idx = 0;char data = new char6;public synchronizedvoid push(char c) dataidx = c;idx+;public synchronized char p

5、op() idx-;return dataidx;public static void main(String args) MyStack m = new MyStack();/*下面对象 m 被加锁。 严格的说是对象m 的所有synchronized无法执行 m块被加锁。如果存在另一个试图访问对象的 push 和pop 方法。m 的线程T,那么T*/m.pop();/ 对象 m 被加锁。Java 的加锁解锁跟多个人排队等一个公共厕位完全一样。第一个人进去后顺手把门从里面锁住,其它人只好排队等。第一个人结束后出来时,门才会打开(解锁)。轮到第二个人进去,同样他又会把门从里面锁住,其它人继续排队

6、等待。用厕所理论可以很容易明白: 一个人进了一个厕位,这个厕位就会锁住,但不会导致另一个厕位也被锁住,因为一个人不能同时蹲在两个厕位里。对于 Java就是说: Java 中的锁是针对同一个对象的,不是针对class 的。看下例: MyStatckm1 = new MyStack();MyStatck m2 = new Mystatck();m1.pop();m2.pop();m1 对象的锁是不会影响 m2 的锁的,因为它们不是同一个厕位。就是说,假设有 3 线程 t1,t2,t3 操作 m1 ,那么这 3 个线程只可能在 m1 上排队等,假设另 2 个线程 t8,t9 在操作 m2 ,那么 t

7、8,t9 只会在 m2 上等待。而 t2 和 t8 则没有关系,即使 m2 上的锁释放了, t1,t2,t3 可能仍要在 m1 上排队。原因无它, 不是同一个厕位耳。 Java 不能同时对一个代码块加两个锁,这和数据库锁机制不同,数据库可以对一条记录同时加好几种不同的锁,请参见:6b151b9a3.html4 何时释放锁?一般是执行完毕同步代码块(锁住的代码块)后就释放锁,也可以用wait() 方式半路上释放锁。wait() 方式就好比蹲厕所到一半,突然发现下水道堵住了,不得已必须出来站在一边, 好让修下水道师傅(准备执行 notify 的一个线程)进去疏通马桶,疏通完毕,师傅大喊一声: 已经

8、修好了(notify) ,刚才出来的同志听到后就重新排队。注意啊, 必须等师傅出来啊,师傅不出来,谁也进不去。也就是说notify后,不是其它线程马上可以进入封锁区域活动了,而是必须还要等 notify 代码所在的封锁区域执行完毕从而释放锁以后,其它线程才可进入。这里是wait 与 notify 代码示例: publicsynchronized char pop() char c;while (buffer.size() = 0) try this.wait(); / 从厕位里出来 catch (InterruptedException e) / ignore it.c = (Characte

9、r)buffer.remove(buffer.size()-1).charValue();return c;public synchronized void push(char c) this.notify(); / 通知那些wait() 的线程重新排队。注意:仅仅是通知它们重新排队。Character charObj = new Character(c);buffer.addElement(charObj);/ 执行完毕,释放锁。那些排队的线程就可以进来了。再深入一些。 由于 wait() 操作而半路出来的同志没收到notify信号前是不会再排队的, 他会在旁边看着这些排队的人(其中修水管师

10、傅也在其中) 。注意,修水管的师傅不能插队,也得跟那些上厕所的人一样排队,不是说一个人蹲了一半出来后,修水管师傅就可以突然冒出来然后立刻进去抢修了,他要和原来排队的那帮人公平竞争,因为他也是个普通线程。如果修水管师傅排在后面,则前面的人进去后,发现堵了,就 wait ,然后出来站到一边,再进去一个,再 wait ,出来,站到一边, 只到师傅进去执行 notify. 这样,一会儿功夫, 排队的旁边就站了一堆人,等着 notify. 终于,师傅进去,然后 notify 了,接下来呢? 1. 有一个 wait 的人(线程)被通知到。2. 为什么被通知到的是他而不是另外一个wait 的人?取决于 JV

11、M. 我们无法预先判断出哪一个会被通知到。也就是说,优先级高的不一定被优先唤醒,等待时间长的也不一定被优先唤醒,一切不可预知!(当然,如果你了解该JVM 的实现,则可以预知) 。3. 他(被通知到的线程)要重新排队。4. 他会排在队伍的第一个位置吗?回答是: 不一定。他会排最后吗?也不一定。但如果该线程优先级设的比较高,那么他排在前面的概率就比较大。5. 轮到他重新进入厕位时,他会从上次wait() 的地方接着执行,不会重新执行。恶心点说就是,他会接着拉巴巴,不会重新拉。6. 如果师傅 notifyAll(). 则那一堆半途而废出来的人全部重新排队。顺序不可知。Java DOC上说, The

12、awakened threads will not be able toproceed until the current thread relinquishes the lock onthis object( 当前线程释放锁前,唤醒的线程不能去执行) 。这用厕位理论解释就是显而易见的事。5 Lock的使用用synchronized关键字可以对资源加锁。用Lock关键字也可以。它是 JDK1.5 中新增内容。用法如下:classBoundedBuffer final Lock lock = new ReentrantLock();final Condition notFull= lock.ne

13、wCondition();final Condition notEmpty = lock.newCondition();final Object items = new Object100;int putptr, takeptr, count;public void put(Object x)throws InterruptedException lock.lock();try while (count = items.length)notFull.await();itemsputptr = x;if (+putptr = items.length) putptr = 0;+count;not

14、Empty.signal(); finally lock.unlock();public Object take() throws InterruptedExceptionlock.lock();try while (count = 0)notEmpty.await();Object x = itemstakeptr;if (+takeptr = items.length) takeptr = 0;-count;notFull.signal();return x; finally lock.unlock();(注:这是 JavaDoc里的例子,是一个阻塞队列的实现例子。所谓阻塞队列,就是一个队

15、列如果满了或者空了,都会导致线程阻塞等待。 Java 里的ArrayBlockingQueue提供了现成的阻塞队列,不需要自己专门再写一个了。)一个对象的lock.lock() 和 lock.unlock() 之间的代码将会被锁住。 这种方式比起 synchronize 好在什么地方?简而言之, 就是对 wait 的线程进行了分类。用厕位理论来描述,则是那些蹲了一半而从厕位里出来等待的人原因可能不一样,有的是因为马桶堵了,有的是因为马桶没水了。通知 (notify) 的时候,就可以喊:因为马桶堵了而等待的过来重新排队(比如马桶堵塞问题被解决了),或者喊,因为马桶没水而等待的过来重新排队 (比如马桶没水问题被解决了)

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论