博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JAVA并发
阅读量:5923 次
发布时间:2019-06-19

本文共 2618 字,大约阅读时间需要 8 分钟。

JAVA并发与厕所理论

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

java 用synchronized解决同步问题

  1. 用法1
    public class Test{    public synchronized void print(){        ....;    } }

    某线程执行print()方法,则该对象将加锁。其它线程将无法执行该对象的所有synchronized块。用厕所时将整个厕所门锁住。

  2. 用法2
    public class Test{    public void print(){        synchronized(this){//锁住本对象            ...;        }    }}

    同用法1, 但更能体现synchronized用法的本质。

  3. 用法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(){        ...;     }}
  4. 静态方法的锁
    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://bexvx.baihongyu.com/

你可能感兴趣的文章
MongoDB: 1. Database
查看>>
使用VBS脚本实现的Hosts文件一键配置
查看>>
ATOM插件activate-power-mode体验笔记
查看>>
socket 和 http
查看>>
九、redis高可用
查看>>
RMAN-08137: WARNING: archived log not deleted, needed for standby or upstream capture process
查看>>
限制Textarea字数并实时显示输入字数统计
查看>>
RPC OVER HTTPS
查看>>
linux的top命令参数详解
查看>>
净空法师:人到这个世间来干什么?做人的意义究竟在哪里?
查看>>
洪泛和广播的区别
查看>>
思科IOS软件命名规则
查看>>
Windows Update的自动更新被关闭了,并且更改按钮是灰色无法更改设置
查看>>
Debian kali2 操作系统Segmentation fault
查看>>
oracle中Where子句顺序是否对SQL性能有影响
查看>>
开源邮件服务器
查看>>
# 180111php编译错误
查看>>
Char类型
查看>>
EIGRP 查看邻居命令详解
查看>>
我的友情链接
查看>>