synchronized的多种用法
用法一 synchronized作用在方法
synchronized作用在方法上有两种情况
1.作用在静态方法上
1public static void main(String[] args) {
2 new Thread(() -> {
3 try {
4 a();
5 } catch (InterruptedException e) {
6 e.printStackTrace();
7 }
8 }, "t1").start();
9 new Thread(() -> {
10 try {
11 a();
12 } catch (InterruptedException e) {
13 e.printStackTrace();
14 }
15 }, "t2").start();
16}
17public static synchronized void a() throws InterruptedException {
18 System.out.println(Thread.currentThread().getName() + "进入了方法a");
19 for (; ; ) {
20 Thread.sleep(2000);
21 }
22}
执行结果
可以得出结论当synchronized作用在静态方法上时持有锁的是当前类, t1线程进入后进入死循环, t2将会一直等待, 发生死锁
2.作用在非静态方法上
1public class SynchronizedTest {
2 public static void main(String[] args) {
3 new Thread(() -> {
4 try {
5 new SynchronizedTest().a();
6 } catch (InterruptedException e) {
7 e.printStackTrace();
8 }
9 }, "t1").start();
10 new Thread(() -> {
11 try {
12 new SynchronizedTest().a();
13 } catch (InterruptedException e) {
14 e.printStackTrace();
15 }
16 }, "t2").start();
17 }
18
19 public synchronized void a() throws InterruptedException {
20 System.out.println(Thread.currentThread().getName() + "进入了方法a");
21 for (; ; ) {
22 Thread.sleep(2000);
23 }
24 }
25}
执行结果
这时候发现t1和t2线程都进入了方法a,所以这时候持锁的是当前对象,两个线程都是new新对象调用了a(),所以他们各玩各的互不影响
synchronized修饰代码块
一般修饰代码块也有两种用法
1.synchronized代码块传入this
1public static void main(String[] args) {
2 new Thread(() -> {
3 try {
4 new SynchronizedTest().a();
5 } catch (InterruptedException e) {
6 e.printStackTrace();
7 }
8 }, "t1").start();
9 new Thread(() -> {
10 try {
11 new SynchronizedTest().a();
12 } catch (InterruptedException e) {
13 e.printStackTrace();
14 }
15 }, "t2").start();
16}
17public void a() throws InterruptedException {
18 synchronized (this) {
19 System.out.println(Thread.currentThread().getName() + "进入了方法a");
20 for (; ; ) {
21 Thread.sleep(2000);
22 }
23 }
24}
两个线程都进入了方法, 这种情况和synchronized修饰非静态方法时是一样的,每次执行到代码块的对象并非同一个
2.synchronized代码块传入class
1public class SynchronizedTest {
2 public static void main(String[] args) {
3 new Thread(() -> {
4 try {
5 new SynchronizedTest().a();
6 } catch (InterruptedException e) {
7 e.printStackTrace();
8 }
9 }, "t1").start();
10 new Thread(() -> {
11 try {
12 new SynchronizedTest().a();
13 } catch (InterruptedException e) {
14 e.printStackTrace();
15 }
16 }, "t2").start();
17 }
18
19 public void a() throws InterruptedException {
20 synchronized (SynchronizedTest.class) {
21 System.out.println(Thread.currentThread().getName() + "进入了方法a");
22 for (; ; ) {
23 Thread.sleep(2000);
24 }
25 }
26 }
27}
这种情况锁的是当前类, 所以t1持锁的时候t2是进不来的
总结:
1.当synchronized作用在静态方法时, 所有线程都共用一把锁
2.当synchronized作用在非静态方法时, 相同实例共用一把锁
3.当synchronized代码块传入类时,所有线程都共用一把锁
4.当synchronized代码块传入this时, 相同实例共用一把锁
作者:wenbo
谢谢站长分享 很有用!