您的位置:首页 > 编程语言 > Java开发

JAVA并发

2015-07-03 18:45 225 查看

JAVA并发与厕所理论

多个进程或线程同时(或着说在同一段时间内)访问同一资源会产生并发问题。用排队上厕所理论很好理解这个问题:人在上厕所时会占用当前厕位,其它要想用这个厕位的人就要等待。

java 用synchronized解决同步问题

用法1
public class Test{
public synchronized void print(){
....;
}
}
某线程执行print()方法,则该对象将加锁。其它线程将无法执行该对象的所有synchronized块。用厕所时将整个厕所门锁住。

用法2
public class Test{
public void print(){
synchronized(this){//锁住本对象
...;
}
}
}
同用法1, 但更能体现synchronized用法的本质。

用法3
public class Test{
private String a = "test";
public void print(){
synchronized(a){//锁住a对象
...;
}
}
public synchronized void t(){
...; //这个同步代码块不会因为print()而锁定.
}
}
执行print(),会给对象a加锁,注意不是给Test的对象加锁,也就是说 Test对象的其它synchronized方法不会因为print()而被锁。同步代码块执行完,则释放对a的锁。用厕所时锁住当前的厕位。

为了锁住一个对象的代码块而不影响该对象其它 synchronized块的高性能写法:

public class Test{
private byte[] lock = new byte[0];
public void print(){
synchronized(lock){
...;
}
}
public synchronized void t(){
...;
}
}

静态方法的锁
public class Test{
public synchronized static void execute(){
...;
}
}
效果同

public class Test{
public static void execute(){
synchronized(TestThread.class){
...;
}
}
}
上厕时要所锁住所有的厕所。

java wait、和notify 理解

一般是执行完毕同步代码块(锁住的代码块)后就释放锁,也可以用wait()方式半路上释放锁。wait()方式就好比蹲厕所到一半,突然发现下水道堵住了,不得已必须出来站在一边,好让修下水道师傅(准备执行notify的一个线程)进去疏通马桶,疏通完毕,师傅大喊一声: "已经修好了"(notify),刚才出来的同志听到后就重新排队。注意啊,必须等师傅出来啊,师傅不出来,谁也进不去。也就是说notify后,不是其它线程马上可以进入封锁区域活动了,而是必须还要等notify代码所在的封锁区域执行完毕从而释放锁以后,其它线程才可进入。

这里是wait与notify代码示例:

public synchronized char pop() {
char c;
while (buffer.size() == 0) {
try {
this.wait(); //从厕位里出来
} catch (InterruptedException e) {
// ignore it...
}
}
c = ((Character)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信号前是不会再排队的,他会在旁边看着这些排队的人(其中修水管师傅也在其中)。注意,修水管的师傅不能插队,也得跟那些上厕所的人一样排队,不是说一个人蹲了一半出来后,修水管师傅就可以突然冒出来然后立刻进去抢修了,他要和原来排队的那帮人公平竞争,因为他也是个普通线程。如果修水管师傅排在后面,则前面的人进去后,发现堵了,就wait,然后出来站到一边,再进去一个,再wait,出来,站到一边,只到师傅进去执行notify. 这样,一会儿功夫,排队的旁边就站了一堆人,等着notify.

终于,师傅进去,然后notify了,接下来呢?

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

来自为知笔记(Wiz)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: