Java的synchronized加在方法上或者对象上有什么区别?

Java的synchronized加在方法上或者对象上有什么区别?



Java的synchronized可以加在方法上,也可以直接加在对象上,从而保证一段代码只能有一个线程在运行,保证线程的同步。

那么这两者究竟有啥区别呢?我们可以看下面的示例代码。

001 public class SyncTest {
002  
003     public static synchronized void testSyncOnStaticMethod() {
004         System.out.println("testSyncOnStaticMethod");
005         try {
006             Thread.sleep(10000);
007         catch (InterruptedException e) {
008         }
009     }
010  
011     public static void testSyncOnClass() {
012         synchronized (SyncTest.class) {
013             System.out.println("testSyncOnClass");
014             try {
015                 Thread.sleep(10000);
016             catch (InterruptedException e) {
017             }
018         }
019     }
020  
021     public synchronized void testSyncOnMethod() {
022         System.out.println("testSyncOnMethod");
023         try {
024             Thread.sleep(10000);
025         catch (InterruptedException e) {
026         }
027     }
028  
029     public void testSyncOnThis() {
030         synchronized (this) {
031             System.out.println("testSyncOnThis");
032             try {
033                 Thread.sleep(10000);
034             catch (InterruptedException e) {
035             }
036         }
037     }
038  
039     public static void case1() {
040         // case1
041         // 先输出testSyncOnThis或者testSyncOnMethod
042         // 然后停顿10秒,再输出另一个
043         // 这个现象表明了
044          
045         // public synchronized void func() {
046         // }
047          
048         // 等价于
049          
050         // public void func() {
051         //     synchronized (this) {
052         //     }
053         // }
054         final SyncTest t1 = new SyncTest();
055         new Thread(new Runnable() {
056  
057             @Override
058             public void run() {
059                 t1.testSyncOnThis();
060             }
061         }).start();
062  
063         new Thread(new Runnable() {
064  
065             @Override
066             public void run() {
067                 t1.testSyncOnMethod();
068             }
069         }).start();
070     }
071  
072     public static void case2() {
073         // case2
074         // 先输出testSyncOnClass或者testSyncOnStaticMethod
075         // 然后停顿10秒,再输出另一个
076         // 这个现象表明了
077          
078         // public synchronized static void staticFunc() {
079         // }
080          
081         // 等价于
082          
083         // public static void staticFunc() {
084         //     synchronized (SyncTest.class) {
085         //     }
086         // }
087         new Thread(new Runnable() {
088  
089             @Override
090             public void run() {
091                 SyncTest.testSyncOnClass();
092             }
093         }).start();
094  
095         new Thread(new Runnable() {
096  
097             @Override
098             public void run() {
099                 SyncTest.testSyncOnStaticMethod();
100             }
101         }).start();
102     }
103  
104     public static void main(String[] args) {
105         case1();
106         case2();
107     }
108 }

从上面的代码我们可以看出synchronized加在方法上本质上还是等价于加在对象上的。

如果synchronized加在一个类的普通方法上,那么相当于synchronized(this)。

如果synchronized加载一个类的静态方法上,那么相当于synchronized(Class对象)。

在使用多线程的时候,知道这个是很关键的,因为synchronized的两种不用用法可能导致两段不相干的代码是互斥的,增加了同步的开销(例如这里的函数testSyncOnThis和testSyncOnMethod,他们在同一个对象this上加了锁),更严重的是可能导致死锁。

注:如果要试验,上面的case1和case2请分开运行(可以跑两次,每次注释掉其中一个语句),这样子可以看得比较清楚。


转自  http://blog.iamzsx.me/show.html?id=126001

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值