正经学徒,佛系记录,不搞事情
8锁即8个关于锁执行顺序的问题
解决问题前,首先需要明白的是 synchronized 只会锁两样东西,一样是调用的对象,一样是Class
public class Test {
public static void main(String[] args) throws InterruptedException {
Fun fun = new Fun();
new Thread(()->{fun.funOne();},"A线程").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{fun.funTwo();},"B线程").start();
}
}
class Fun{
public synchronized void funOne(){
System.out.println(Thread.currentThread().getName()+":调用方法一");
}
public synchronized void funTwo(){
System.out.println(Thread.currentThread().getName()+":调用方法二");
}
}
判断执行顺序,先判断什么被锁了,这里synchronized锁的是Fun对象new出来的fun,因为先调用了funOne睡1秒后调用的funTwo,funTwo需要等到funOne释放锁后才会执行
最终执行结果是:A线程:调用方法一 B线程:调用方法二
public class Test {
public static void main(String[] args) throws InterruptedException {
Fun fun = new Fun();
new Thread(()->{
try { fun.funOne(); } catch (InterruptedException e) { e.printStackTrace(); }
},"A线程").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{fun.funTwo();},"B线程").start();
}
}
class Fun{
public synchronized void funOne() throws InterruptedException {
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName()+":调用方法一");
}
public synchronized void funTwo(){
System.out.println(Thread.currentThread().getName()+":调用方法二");
}
}
该情况其实和问题一 一样,synchronized锁的是Fun对象new出来的fun,当调用funOne时,fun被锁,而程序不受funOne内睡的影响继续执行,在调用funTwo的时候因为fun被锁导致等待,当funOne执行完后funTwo瞬间执行
最终执行结果是:3 秒后同时出现 A线程:调用方法一 B线程:调用方法二
public class Test {
public static void main(String[] args) throws InterruptedException {
Fun fun = new Fun();
new Thread(()->{
try { fun.funOne(); } catch (InterruptedException e) { e.printStackTrace(); }
},"A线程").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{fun.funTwo();},"B线程").start();
}
}
class Fun{
public synchronized void funOne() throws InterruptedException {
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName()+":调用方法一");
}
public void funTwo(){
System.out.println(Thread.currentThread().getName()+":调用方法二");
}
}
程序执行在funOne中锁了fun并在方法中睡3秒,外部在睡1秒后调用funTwo,因为无锁因此直接执行
最终执行结果是:1 秒后出现B线程:调用方法二 再2秒后出现 A线程:调用方法一
public class Test {
public static void main(String[] args) throws InterruptedException {
Fun fun1 = new Fun();
Fun fun2 = new Fun();
new Thread(()->{
try { fun1.funOne(); } catch (InterruptedException e) { e.printStackTrace(); }
},"A线程").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{fun2.funTwo();},"B线程").start();
}
}
class Fun{
public synchronized void funOne() throws InterruptedException {
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName()+":调用方法一");
}
public synchronized void funTwo(){
System.out.println(Thread.currentThread().getName()+":调用方法二");
}
}
程序调用funOne时锁住fun1,外部睡1秒后调用funTwo时锁funTwo,互不影响
最终执行结果是:B线程:调用方法二 A线程:调用方法一
public class Test {
public static void main(String[] args) throws InterruptedException {
Fun fun = new Fun();
new Thread(()->{
try { fun.funOne(); } catch (InterruptedException e) { e.printStackTrace(); }
},"A线程").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{fun.funTwo();},"B线程").start();
}
}
class Fun{
public static synchronized void funOne() throws InterruptedException {
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName()+":调用方法一");
}
public static synchronized void funTwo(){
System.out.println(Thread.currentThread().getName()+":调用方法二");
}
}
这里多了静态static,因此此时锁的东西改变了,funOne和funTwo都是锁的Fun这个class,程序在执行funOne时锁住Fun class,睡1秒后调用funTwo,funTwo等待funOne内睡完释放锁后再执行
最终执行结果是:A线程:调用方法一 B线程:调用方法二
public class Test {
public static void main(String[] args) throws InterruptedException {
Fun fun1 = new Fun();
Fun fun2 = new Fun();
new Thread(()->{
try { fun1.funOne(); } catch (InterruptedException e) { e.printStackTrace(); }
},"A线程").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{fun2.funTwo();},"B线程").start();
}
}
class Fun{
public static synchronized void funOne() throws InterruptedException {
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName()+":调用方法一");
}
public static synchronized void funTwo(){
System.out.println(Thread.currentThread().getName()+":调用方法二");
}
}
要注意的是,不管现在new结果对象,调用方法后锁的都是Fun class,funTwo会被funOne阻塞
最终执行结果是:A线程:调用方法一 B线程:调用方法二
public class Test {
public static void main(String[] args) throws InterruptedException {
Fun fun = new Fun();
new Thread(()->{
try { fun.funOne(); } catch (InterruptedException e) { e.printStackTrace(); }
},"A线程").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{fun.funTwo();},"B线程").start();
}
}
class Fun{
public static synchronized void funOne() throws InterruptedException {
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName()+":调用方法一");
}
public synchronized void funTwo(){
System.out.println(Thread.currentThread().getName()+":调用方法二");
}
}
同样只要确认锁的是不是一个东西就知道会不会阻塞,调用funOne时阻塞的是Fun class,调用funTwo时阻塞的是fun
最终执行结果是:B线程:调用方法二 A线程:调用方法一
public class Test {
public static void main(String[] args) throws InterruptedException {
Fun fun1 = new Fun();
Fun fun2 = new Fun();
new Thread(()->{
try { fun1.funOne(); } catch (InterruptedException e) { e.printStackTrace(); }
},"A线程").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{fun2.funTwo();},"B线程").start();
}
}
class Fun{
public static synchronized void funOne() throws InterruptedException {
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName()+":调用方法一");
}
public synchronized void funTwo(){
System.out.println(Thread.currentThread().getName()+":调用方法二");
}
}
解题跟问题七一致,调用funOne时阻塞的是Fun class,调用funTwo时阻塞的是fun2
最终执行结果是:B线程:调用方法二 A线程:调用方法一