最近在看多线程,参考了一篇 博客 ,觉得写得比较好,但是在一段相关对象锁的代码上卡住了,理解不了,问了同学,加上自己的理解,终于搞懂了。
测试代码
package com.fehead.test;
import com.fehead.thread.MyThreadPrinter;
public class Test {
public static void main(String[] args) throws Exception {
Object a = new Object();
Object b = new Object();
Object c = new Object();
MyThreadPrinter pa = new MyThreadPrinter("A", c, a);
MyThreadPrinter pb = new MyThreadPrinter("B", a, b);
MyThreadPrinter pc = new MyThreadPrinter("C", b, c);
new Thread(pa).start();
Thread.sleep(100);
new Thread(pb).start();
Thread.sleep(100);
new Thread(pc).start();
Thread.sleep(100);
}
}
package com.fehead.thread;
public class MyThreadPrinter implements Runnable {
private String name;
private Object prev;
private Object self;
public MyThreadPrinter(String name, Object prev, Object self) {
this.name = name;
this.prev = prev;
this.self = self;
}
@Override
public void run() {
int count = 10;
while(count > 0) {
synchronized (prev) {
synchronized (self) {
System.out.print(name);
count--;
self.notify();
}
try {
prev.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
输出结果
- ABCABCABCABCABCABCABCABCABCABC
个人理解
-
从
sleep()
开始,Thread.sleep(100);
能让线程暂停100ms
,可以看到线程pa
没有线程休眠,线程pb
休眠了100ms
,而线程pc
休眠了200ms
(至于第三个Thread.sleep(100);
有什么作用我还没搞懂,欢迎大神留言解惑)。 -
对象锁,顾名思义,实际上是一把锁,
wait()
是锁,而prev
,self
(对象a,b,c)是锁孔的形状,相对的notify()
是钥匙,与之对应的prev
,self
(对象a,b,c)是钥匙的形状。 -
回到代码
- 首先开始的是
pa
同学,他先拿起了c
锁,然后又拿起了a
锁,用钥匙打开了a
锁(虽然a
锁并没有锁住任何东西···),接着放下了a
锁,用c
锁把自己锁住了,最后放下了c
锁; - 接下来是
pb
同学,他一上来就要拿a
锁,(但是pa
比他快了一步,所以他只能等pa
放下a
锁后再拿a
锁 1), 接着他有拿到了b
锁,用钥匙打开了b
锁(虽然b
锁也没有锁住任何东西···),接着放下了b
锁,用a
锁把自己锁住了,最后放下了a
锁; - 最后是
pc
同学,他先拿起了b
锁,然后又拿起了c
锁,用钥匙打开了c
锁,还记的用c
锁把自己锁起来的pa
吧,这个时候他就被放了出来,所以他又开始行动了,接着pc
放下了c
锁,用b
锁把自己锁住了,最后放下了b
锁; - 话说
pa
被pc
放出来了,他又拿起了c
锁,然后又拿起了a
锁,用钥匙打开了a
锁(a
锁原本锁住的pb
被放了出来),接着放下了a
锁,用c
锁把自己锁住了,最后放下了c
锁; - 话说
pb
被pa
放出来了,他又拿起了a
锁,然后又拿起了b
锁,用钥匙打开了b
锁(b
锁原本锁住的pc
被放了出来),接着放下了b
锁,用a
锁把自己锁住了,最后放下了a
锁; - ······
- 如此往复,因为
while()
循环了10次,因此顺序输出ABC10次。
- 首先开始的是
-
图片理解
理解错误
我在理解对象锁的时候有过一个错误,认为每一个对象锁对应一个线程,a
对应pa
,b
对应pb
,c
对应pc
,实际上wait()
是使本线程休眠,也就是不管是哪个对象锁,运行wait()
锁住的一定是本线程。
因为是个人理解,所以不一定正确,如果有错误,欢迎大佬指正。
这句话是为了说明不同的线程不能同时调用同一个对象锁 ↩︎