Java高并发编程详解-多线程架构与设计:线程间的通信

    科技2025-09-08  58

    同步、异步、阻塞、非阻塞概念

    同步和异步 结果的通知机制。自己问还是别人通知。 同步:主动等待结果的返回。如阻塞等待,轮询(同步非阻塞)。 异步:被动等待结果的返回。如 消息回调。

    阻塞和非阻塞 结果返回以前,调用方的状态。等还是不等。 阻塞:结果返回以前,什么也不干。

    非阻塞:在结果返回以前,可以先做一些其他事情。

    Monitor锁

    下面所说的获取monitor锁都是指的先使用synchronized获取对象锁 不应该叫synchronized(mutex)为锁,而应该是某个线程获取了与mutex关联的monitor锁。

    wait 与 notify

    wait 理解成线程在等待直到该对象可用。(被notify后就不再等待)

    notify理解成线程通知该对象可用。

    使用wait的注意事项

    wait必须在同步方法中使用,因为wait必须由拥有monitor(已用synchronize获取锁)的线程调用。wait可以被中断,为了防止wait被interrupt唤醒,wait方法需要在循环中使用。使用wait后自动释放线程对应的锁。–release ownership of this monitorwait会等待直到其他线程调用notify/notifyAll唤醒。–waits until anthoer thread notifies threads waiting on this object’s monitor to wake up…被notify/notifyAll唤醒后会重新获得锁的拥有权,然后接着执行。–re-obtain ownership of the monitor and resumes execution.线程调用wait后, 会加入与之对应的wait set.每个对象都有一个与之对应的wait set.使用notify会将其中一个弹出,notifyAll弹出所有线程。(C5.3.2)Causes the current thread to wait until another thread invokes the * {@link java.lang.Object#notify()} method or the * {@link java.lang.Object#notifyAll()} method for this object. * In other words, this method behaves exactly as if it simply * performs the call {@code wait(0)}. * * The current thread must own this object’s monitor. The thread * releases ownership of this monitor and waits until another thread * notifies threads waiting on this object’s monitor to wake up * either through a call to the {@code notify} method or the * {@code notifyAll} method. The thread then waits until it can * re-obtain ownership of the monitor and resumes execution. * As in the one argument version, interrupts and spurious wakeups are * possible, and this method should always be used in a loop: * synchronized (obj) { * while (<condition does not hold>) * obj.wait(); * … // Perform action appropriate to condition * } * This method should only be called by a thread that is the owner * of this object’s monitor. See the {@code notify} method for a * description of the ways in which a thread can become the owner of a monitor.

    使用notify的注意

    必须在同步方法中使用wait、notify,因为他们的使用前提都是持有monitor所有权。同步代码块的monitor必须与执行 wait 、notify的对象一致,也就是说对哪个对象同步,才能调用哪个对象的 wait、notify。

    例子:

    若不是用的notifyAll, 则不能用于多线程环境

    在while而不是if中调用wait!否则一旦被interrupt,会跳过判断继续执行。如

    测试主动interrupt对if中使用wait的影响

    这里主动interrupt,可见当producer被interrupt后,producer就略过了判断,继续添加了一个event

    wait与sleep的

    相同: 使线程阻塞 可以中断不同: wait是Object的方法,sleep是Thread的 wait必须要在同步代码块中执行。 wait会释放monitor的锁,sleep不会 sleep短暂休眠后会退出阻塞?(TODO)wait(没有指定时间的话)必须被中断才会退出阻塞。

    synchronized的缺点

    无法中断 synchronized不像sleep和wait那样,可以被中断。没有等待时间 其他线程获取锁的拥有权必须要等待锁的拥有者(线程)释放后才能执行。

    利用wait、notify实现可中断的BooleanLock

    p96-104 一旦从wait中被唤醒则有机会检查lock是否为false,为false则修改获取锁的线程cureentLockThread为自己,并设置lock为true.防止其他线程继续争抢。 如果wait超时会报错,notify后超时 也主动抛错。

    关键代码

    从wait中被notify或者等待超时后,会因为while(locked),locked为false,说明没有线程持有monitor的拥有权,因此跳出while设置locked=true;this.currentThread=currentThread();

    优化,超时后清除blackList

    Processed: 0.013, SQL: 8