如果一个线程加锁后,但是,资源一直迟迟不来,就会一直加锁。
这个时候,进行 wait
就会进入到 waitset
变为 waiting
状态。
等有资源后,通过 notify
或者 notifyAll
唤醒,然后进入 EntryList
重新竞争。
waiting
是已经获得了锁,但是调用 wait
后的状态。
API
- obj.wait()
- 让进入 object 监视器的线程到
waitset
等待
- wait 里面可以传递参数,这里不再详细说明
- obj.notify()
- 在
object
上正在 waitset
等待的线程挑一个唤醒
- obj.notifyAll()
- 让
object
上正在 waitset
等待的线程全部唤醒
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| package com.redisc;
import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.openjdk.jol.info.ClassLayout;
import java.util.concurrent.TimeUnit;
@Data class User { }
@Slf4j(topic = "c.Test") public class Test { static final Object lock = new Object(); // 加上 final 保证锁的引用不替换
public static void main(String[] args) throws Exception { new Thread(() -> { synchronized (lock) { log.debug("执行"); try { lock.wait(); } catch (Exception e) { e.printStackTrace(); } } }, "t1").start();
new Thread(() -> { synchronized (lock) { log.debug("执行..."); try { lock.wait(); } catch (Exception e) { e.printStackTrace(); } } }).start();
log.debug("其他代码"); synchronized (lock) { log.debug("唤醒一个随机线程"); lock.notify(); // lock.notifyAll(); // 唤醒全部 } }
}
|
输出
1 2 3 4
| 22:32:05.534 [t1] DEBUG c.Test - 执行 22:32:05.534 [main] DEBUG c.Test - 其他代码 22:32:05.536 [Thread-0] DEBUG c.Test - 执行... 22:32:05.536 [main] DEBUG c.Test - 唤醒一个随机线程
|
sleep 和 wait 的区别
sleep
是 Thread
方法,wait
是 Object
的方法
sleep
不需要强制和 synchronized
配合使用,但是 wait
需要和 synchronized
一起用
sleep
在睡眠的同时,不会释放对象锁,但是,wait
在等待的时候会释放对象锁