您的位置:首页 > 编程语言 > Java开发

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

2014-02-26 12:35 507 查看


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

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

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

view
source

print?

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐