synchronized 原理:
假设有4个线程(A,B,C,D),假设线程A拿到了锁,执行锁内代码,线程BCD没有抢到锁,就会被存入sysnchronized底层blockedThreads(没有获取到锁的线程)的entrylist中,等到线程A执行完代码就会重新唤醒entrylist中阻塞的线程BCD重新争抢获取锁的资源。
join:
使得t.join()中的t优先执行,当t执行完后才会执行其他线程。能够使得线程之间的并行执行变成串行执行。
首先写三个线程,先不使用join
Thread test1 = new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "线程1运行");
}, "test1");
Thread test2 = new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "线程2运行");
}, "test2");
Thread test3 = new Thread(() -> {
System.out.println(Thread.currentThread().getName() + "线程3运行");
}, "test3");
test1.start();
test2.start();
test3.start();
执行结果:
test2线程2运行
test3线程3运行
test1线程1运行
使用join后代码
Thread test1 = new Thread(() -> {
//test1执行完毕会唤醒test2
System.out.println(Thread.currentThread().getName() + "线程1运行");
}, "test1");
Thread test2 = new Thread(() -> {
try {
//test2 调用了test1(this=test2).wait() test2变成了阻塞状态
test1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "线程2运行");
}, "test2");
Thread test3 = new Thread(() -> {
try {
test2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "线程3运行");
}, "test3");
test1.start();
test2.start();
test3.start();
}
代码执行结果:线程按照 test1-> test2->test3执行
test1线程1运行
test2线程2运行
test3线程3运行
join源码
public final synchronized void join(long millis)
throws InterruptedException {
// synchronized(this) this = 当前调用的线程
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
//join的底层使用了 wait方法
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
总结:
Join底层原理是基于wait封装的,(唤醒代码不在Java代码中)唤醒的代码在jvmHotspot源码中,当jvm在关闭线程之前会检测线阻寒在t1线程对象上的线程,然后执行notfyAll(),这样t2就被唤醒,取消阻塞。