线程“八锁“ synchronized到底是对哪个对象加锁?
创始人
2024-02-21 09:27:46

线程"八锁" synchronized到底是对哪个对象加锁?

习题一

class Number{public synchronized void a(){System.out.println("1");}public synchronized void b(){System.out.println("2");}
}
public class TestBlock {public static void main(String[] args) throws InterruptedException {Number n = new Number();Thread t1 = new Thread(()->{System.out.println("t1->begin!!!");n.a();});Thread t2 = new Thread(()->{System.out.println("t2->begin!!!");n.b();});t1.start();t2.start();t1.join();t2.join();}
}

对于Number类里面的a方法和b方法都是对当前对象this加锁,也就是对Number对象加锁.

当两个线程通过对象调用两个方法(a和b)的时候,会产生互斥效果-->锁的都是同一个对象(Number对象)

对于打印结果取决于任务调度器先调度谁就先打印谁,两者都有机会被优先调度,所以打印顺序可能是 1 2 也可能是2 1.

习题二

class Number1{public synchronized void a(){System.out.println("1");}public synchronized void b(){System.out.println("2");}
}
public class TestBlock1 {public static void main(String[] args) throws InterruptedException {Number1 n = new Number1();Thread t1 = new Thread(()->{try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("t1->begin!!!");n.a();});Thread t2 = new Thread(()->{System.out.println("t2->begin!!!");n.b();});t1.start();t2.start();t1.join();t2.join();}
}

对比习题1就相当于在t1线程里面多加了个sleep,让其t1线程睡眠一会.

但是,t1线程和t2线程锁的还是同一个对象Number具有互斥效果.

打印结果还是取决于任务调度器的调度,如果先调度的是t1(t1先拿到锁),那么就等待1s后,执行a方法打印1,然后线程2在执行b方法,打印2.

还有一种情况是任务调度器先调度t2线程,就会先打印2,然后睡眠1s后打印1.

习题3

class Number3{public synchronized void a(){System.out.println("1");}public synchronized void b(){System.out.println("2");}public void c(){//没有加锁System.out.println("3");}
}
public class TestBlock3 {public static void main(String[] args) throws InterruptedException {Number3 n = new Number3();Thread t1 = new Thread(()->{try {Thread.sleep(10000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("t1->begin!!!");n.a();});Thread t2 = new Thread(()->{System.out.println("t2->begin!!!");n.b();});Thread t3 = new Thread(()->{System.out.println("t3->begin!!!");n.c();});t1.start();t2.start();t3.start();t1.join();t2.join(); t3.join();}
}

习题3是多加了一个方法c,但是方法c没有加synchronized.

对于这个题,方法a,b都加了synchronized可以其互斥效果,但是反方c没有加synchronized,不会被加锁.也就是线程1或者线程2执行,线程3不会阻塞,依然会继续往后执行.

对于打印结果还是取决于任务调度器的调度.

如果先调度的是线程1,那么会等待1s后打印1,但是方法c没有加锁,所以不会阻塞,线程3执行方法c打印3,然后1s后打印1 ,线程1释放锁之后唤醒线程2,线程2执行b方法打印2.====> 3 一秒后 1 2

由于线程2和线程3是并发执行的取决于任务调度器

如果先调度的是线程2,那么会先打印 2 ,然后线程3并发/并行的执行方法c打印3,然后一秒后打印1

===> 2 3 一秒后 1

如果先调度的是线程3,那么会先打印 3 ,然后线程2并发/并行的执行方法b打印2,然后一秒后打印1

===> 3 2 一秒后 1

习题4

class Number4{public synchronized void a(){System.out.println("1");}public synchronized void b(){System.out.println("2");}
}
public class TestBlock4 {public static void main(String[] args) throws InterruptedException {Number4 n1 = new Number4();Number4 n2 = new Number4();Thread t1 = new Thread(()->{try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("t1->begin!!!");n1.a();});Thread t2 = new Thread(()->{System.out.println("t2->begin!!!");n2.b();});t1.start();t2.start();t1.join();t2.join();}
}

这个题有两个对象n1和n2.

有两个对象,n1.a(),n2.b(),既然是不同的对象,也就是线程1和线程2对不同的对象加锁=>锁的不是同一个对象不产生互斥效果,并发/并行的执行,但由于t1线程睡眠1s钟,所以总是先打印2 一秒后 在打印1

习题5

class Number5{public synchronized static void a(){System.out.println("1");}public synchronized void b(){System.out.println("2");}
}
public class TestBlock5 {public static void main(String[] args) throws InterruptedException {Number5 n = new Number5();Thread t1 = new Thread(()->{try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("t1->begin!!!");n.a();});Thread t2 = new Thread(()->{System.out.println("t2->begin!!!");n.b();});t1.start();t2.start();t1.join();t2.join();}
}

线程1调用a方法,a是静态方法,对静态方法加锁相当于是对类对象加锁-->锁的是Number类对象

线程2调用b方法,b是非静态方法,相当于对this对象加锁->也就是n对象

所以锁的是不同的对象==>对不同的对象进行加锁--->不会产生互斥效果

所以两线程是并发执行的,由于睡眠,先打印2,一秒后打印1

习题6

class Number6 {public synchronized static void a(){System.out.println("1");}public synchronized static void b(){System.out.println("2");}
}
public class TestBlock6 {public static void main(String[] args) throws InterruptedException {Number6 n = new Number6();Thread t1 = new Thread(()->{try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("t1->begin!!!");n.a();});Thread t2 = new Thread(()->{System.out.println("t2->begin!!!");n.b();});t1.start();t2.start();t1.join();t2.join();}
}

两个线程调用的方法都是对静态方法进行加锁==>都是对类对象加锁-->锁的是相同对象-->产生互斥效果.

取决于任务调度器. 先调度线程1就是 1s之后打印1 ,然后打印2,否则的话先调度线程2就是 打印2 ,1s之后然后打印1

习题7

class Number7 {public synchronized static void a(){System.out.println("1");}public synchronized  void b(){System.out.println("2");}
}
public class TestBlock7 {public static void main(String[] args) {Number7 n1 = new Number7();Number7 n2 = new Number7();Thread t1 = new Thread(()->{try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}n1.a();});Thread t2 = new Thread(()->{n2.b();});t1.start();t2.start();}
}

加锁的对象不一样,线程1调用的方法对类对象加锁,线程2里面利用n2对象调用b方法,对n2对象加锁,所以两个线程是对不同的对象进行加锁->不产生互斥效果.

所以线程1和线程2是并发执行的,所以是先打印2,一秒后打印1

习题8

class Number8{public static synchronized void a() {System.out.println("1");}public static synchronized void b() {System.out.println("2");}
}
public class TestBlock8 {public static void main(String[] args) {Number8 n1 = new Number8();Number8 n2 = new Number8();Thread t1 = new Thread(()->{try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}n1.a();});Thread t2 = new Thread(()->{n2.b();});t1.start();t2.start();}
}

虽然是不同的对象调用方法

但是调用的方法都是对静态方法进行加锁==>都是对类对象加锁-->锁的是相同对象-->产生互斥效果.

取决于任务调度器. 先调度线程1就是 1s之后打印1 ,然后打印2,否则的话先调度线程2就是 打印2 ,1s之后然后打印1

总结

分析这种问题,首先往最根头看起,到底锁的对象是谁,是this还是类对象,还是没有加锁,然后在确定多个对象是否是锁的同一个对象

  • 如果锁的是同一个对象,那么会产生互斥效果,一个线程没有执行完,另外一个线程阻塞等待.
  • 锁的不是同一个对象,那么就不会产生互斥效果,并行的执行
  • 如果没有加锁,那么也是会与其他线程并行的执行

然后具体情况具体分析,可能分为多种情况-->这种情况就要考虑任务调度器的调度执行了.--->分多种情况去考虑即可

参考 :

黑马程序员JUC视频-->哔哩哔哩

相关内容

热门资讯

承当的解释及造句 承当的解释及造句  承当拼音  【注音】: cheng dang  承当解释  【意思】:(1)担当...
讽刺造句   讽刺造句  1、我们不能讽刺那些聋哑人。  2、如果有人讽刺我的惨境,我会以冷漠回应。  3、他...
线装的造句 线装的造句  【注音】: xian zhuang  线装解释  【意思】:书籍装订法的一种,装订的线...
用一望无际造句 用一望无际造句  蔚蓝色的大海广阔无垠、一望无际,而海面下却是另一番多彩的世界。下面是小编收集整理的...
用是什么也是什么造句   下面是小编给大家整理的用是什么也是什么造句,欢迎大家查看。  1. 处分你是为了教育你,也是为了...