这段程序到底是锁定的那个对象?

ldhscxl 2010-05-14 11:14:14
下面这段程序到底是锁定的tt对象呢?还是分别锁定的inc和dec对象呢?

public class ThreadTest {
private int j;

public static void main(String args[]) {
ThreadTest tt = new ThreadTest();
Inc inc = tt.new Inc();
Dec dec = tt.new Dec();
for (int i = 0; i < 2; i++) {
Thread t = new Thread(inc);
t.start();
t = new Thread(dec);
t.start();
}
}

private synchronized void inc() {
j++;
System.out.println(Thread.currentThread().getName() + "-inc:" + j);
}

private synchronized void dec() {
j--;
System.out.println(Thread.currentThread().getName() + "-dec:" + j);
}

class Inc implements Runnable {
public void run() {
for (int i = 0; i < 100; i++) {
inc();
}
}
}

class Dec implements Runnable {
public void run() {
for (int i = 0; i < 100; i++) {
dec();
}
}
}
}
...全文
345 30 打赏 收藏 转发到动态 举报
写回复
用AI写文章
30 条回复
切换为时间正序
请发表友善的回复…
发表回复
yhcdio 2010-05-17
  • 打赏
  • 举报
回复
我觉得synchornized 方法类似于synchornized(this), synchornized(obj)是根据指定对象obj的锁来同步。
ldhscxl 2010-05-17
  • 打赏
  • 举报
回复
恩,谢谢各位的热情回答,现在对锁定那个对象有了新的理解。
  • 打赏
  • 举报
回复
这个区别仅在于 JVM 指令数量上,对于功能和锁的作用范围是一样的。
wingardium 2010-05-15
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 qybao 的回复:]
另外,synchronized method的时候,当有线程进入该方法时,其他线程一样可以访问该对象的其他方法……
[/Quote]
不够准确,应该是,当有线程进入该方法时,其它线程可以同时访问该对象的其它“非同步”方法。
lodachi 2010-05-14
  • 打赏
  • 举报
回复
锁的是方法
qybao 2010-05-14
  • 打赏
  • 举报
回复
锁定tt的inc和dec方法,不锁定tt对象


[Quote=引用 2 楼 goldenfish1919 的回复:]
Java code

private synchronized void inc() {
j++;
System.out.println(Thread.currentThread().getName() + "-inc:" + j);
}
等价于:
private void inc() {
synchronized(this……
[/Quote]

这样是不等价的,你可以在synchronized(this)之前加上System.out.println()就知道了
synchronized void inc()是锁定方法,只有一个线程能进入方法
synchronized(this)是锁定对象,只有一个线程能使用对象,但是多个线程能同时进入inc方法,只是在synchronized(this)处发生解锁等待


qybao 2010-05-14
  • 打赏
  • 举报
回复
这个高效的问题是在synchronized(this)作用于整个函数的前提下比较的,如果像你所说的,只是某部分synchronized,那就回到我上面所说的现象,如果只是部分synchronized(this),那synchronized method和synchronized(this)在处理结果上就有可能不一样,也就是说synchronized method和synchronized(this)并不一定等价,我也觉得同步方法的并发性不好,我也没想到书中是这样的答案,具体什么样的处理性能更好,这需要具体问题具体分析,我这里只是想说明synchronized method和synchronized(this)是有区别的

若鱼1919 2010-05-14
  • 打赏
  • 举报
回复

private synchronized void inc() {
j++;
System.out.println(Thread.currentThread().getName() + "-inc:" + j);
}
等价于:
private void inc() {
synchronized(this){
j++;
System.out.println(Thread.currentThread().getName() + "-inc:" + j);
}
}
也就是说,是锁定tt对象
eimhee 2010-05-14
  • 打赏
  • 举报
回复
synchronized 加在方法前是说只能容许单个线程进入这个方法

private synchronized void inc() {
j++;
System.out.println(Thread.currentThread().getName() + "-inc:" + j);
}

  • 打赏
  • 举报
回复
根据《深入java虚拟机》的描述,同步方法与同步块只是在字节码上面更加高效。但是我认为虽然在字节码上高效,但是相对于只保护方法中部分代码而言,同步方法的并发性要更差一些。

我感觉应该从细粒度上来考虑同步。如果什么都不管只在方法上加个同步关键字,我并不认为效率会高,有时候
只是这个方法中的部分几行代码需要进行同步处理,并不需要将整个方法锁住。
qybao 2010-05-14
  • 打赏
  • 举报
回复
纠正一下我所说的锁方法的说法,是我表达不好,其实我更多的是从底层的编译去考虑,锁只是针对对象而言
但是我还是坚持synchronized method和synchronized(this)有区别,这是经验告诉了我,我虽然不能很好地解释,我自己查了一下《深入java虚拟机》第二版,第347-353页,上面有说两种的区别,功能上是一致的,即处理结果是一样的,但synchronized method更高效,有兴趣的人自己去看吧
茫茫大海 2010-05-14
  • 打赏
  • 举报
回复
锁定只会是对象,不能是方法,上面的inc和dec都是TestThread类的成员方法,所以锁定的对象应该是该方法所属的对象,即tt。
humanity 2010-05-14
  • 打赏
  • 举报
回复
简单地说是:
通过 t = new Thread(xx) 后得到的一共4个线程尝试锁住 ThreadTest 对象,某个时刻获得 ThreadTest 对象的锁的话就可以执行 inc () 或 dec () 方法,要弄明白锁住哪个对象,其实你主要关注你需要保护哪个对象的状态(不是方法)。
qybao 2010-05-14
  • 打赏
  • 举报
回复
获得锁权限是从synchronized块开始的应该都认同吧,既然如此,synchronized在不同的位置,就是不一样,只不过说结果一样了,但要明白其中是有区别的
比如有某个入口,入口有两扇门,我们把它分为外门和内门,当锁外门的时候(即synchronized method),人是通不过入口进入里面的(即进不来方法内部),当锁内门的时候(即synchronized(this)),人也是通不过入口进入进入里面的,从结果来说,是一样的,都是人不能通过入口进入里面,但从锁的角度来说,是不一样的,因为锁外面,人还可以进入到外门和内门之间。当然,也可以同时锁两扇门,即两个synchronized同时用,结果也是一样的,但从锁的角度来说,也是不一样的,必须先获得第一个锁的权限,才有资格获得第二个所的机会。
另外,synchronized method的时候,当有线程进入该方法时,其他线程一样可以访问该对象的其他方法,可以自己写代码去test,我就不多说的了,以后可以自己在实践中多多体会。如果只知道的结果而不考虑其中的区别,那就忽略我所说的
mochibing 2010-05-14
  • 打赏
  • 举报
回复
正解,两种写法都表示线程要获得该实例的锁才能运行被synchronized修饰的代码

[Quote=引用 19 楼 bao110908 的回复:]
Java code
public synchronized void xxxx() {
aaaa;
bbbb;
cccc;
}



public void xxxx() {
synchronized(this) {
aaaa;
bbbb;
cccc;
}
}


是一样的……
[/Quote]
  • 打赏
  • 举报
回复
public synchronized void xxxx() {
aaaa;
bbbb;
cccc;
}



public void xxxx() {
synchronized(this) {
aaaa;
bbbb;
cccc;
}
}


是一样的,没有区别
qybao 2010-05-14
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 wingardium 的回复:]
引用 16 楼 qybao 的回复:
是不一样的,获得锁的时点和地址是不一样的
一个简单的例子
synchronized void xxx() {
//一旦线程进入方法,其他线程就要等待
}
void xxx() {
//做一些额外处理
synchronized(this) {
//当某个线程进到这里,其他线程才会发生等待,在线程进入之前,多个线程可同时进入方法,处理上面的额外处……
[/Quote]
从处理结果来说是等价的,从处理获得锁的时点和地址来说是不一样的,因为多线程可能同时进入了方法,只是在synchronized(this)的地方发生等待
wingardium 2010-05-14
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 qybao 的回复:]
是不一样的,获得锁的时点和地址是不一样的
一个简单的例子
synchronized void xxx() {
//一旦线程进入方法,其他线程就要等待
}
void xxx() {
//做一些额外处理
synchronized(this) {
//当某个线程进到这里,其他线程才会发生等待,在线程进入之前,多个线程可同时进入方法,处理上面的额外处理,如果没有上面的额外处理,从结果来说,和synchronized void xxx是一样的,但是从锁的角度来说是不一样的
}
}[/Quote]
我说的是,2楼写的两种形式是等价的。如果方法中除了同步代码外还有有额外处理,效果当然不一样。
qybao 2010-05-14
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 wingardium 的回复:]
引用 3 楼 qybao 的回复:
锁定tt的inc和dec方法,不锁定tt对象



引用 2 楼 goldenfish1919 的回复:
Java code

private synchronized void inc() {
j++;
System.out.println(Thread.currentThread().getName() + "-inc:" + j);
……
[/Quote]
是不一样的,获得锁的时点和地址是不一样的
一个简单的例子
synchronized void xxx() {
//一旦线程进入方法,其他线程就要等待
}
void xxx() {
//做一些额外处理
synchronized(this) {
//当某个线程进到这里,其他线程才会发生等待,在线程进入之前,多个线程可同时进入方法,处理上面的额外处理,如果没有上面的额外处理,从结果来说,和synchronized void xxx是一样的,但是从锁的角度来说是不一样的
}
}



Eric1006 2010-05-14
  • 打赏
  • 举报
回复
无论synchronized关键字加在方法上还是对象上,他取得的锁都是对象,而不是把一段代码或函数当作锁――而且同步方法很可能还会被其他线程的对象访问。
加载更多回复(9)

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧