对多线程中synchronized块的理解问题

fly2749 2010-06-26 06:32:13
在spring的源码中,看到了关于synchronized的关键字的语句,但是对多线程的概念理解不是很清晰,所以想询问下高手。


protected final void refreshBeanFactory() throws BeansException {
// Shut down previous bean factory, if any.
synchronized (this.beanFactoryMonitor) {
if (this.beanFactory != null) {
this.beanFactory.destroySingletons();
this.beanFactory = null;
}
}
....................
............
}

这是spring中的一段代码,比较混乱的是synchronized后括号中的对象,在多线程中有很多定义同步的实现方法,来解决数据的安全性,我知道如果后面跟的是this,那应该是调用这个方法的对象的值。那么如果写明一个object的类型的对象作为参数,应该是什么意思呢,(this.beanFactoryMonitor)
看了解释,似乎应该是这个对象作为锁,如果哪个线程得到了这个对象的锁,就可以执行下面的代码块,那么不明白的是,怎么样判断哪个线程可以得到这个对象的锁呢,这个参数比较不理解,请高手帮解释下,谢谢
ps:如果上面有说的错误的,请帮忙更正,谢谢
...全文
329 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
小湘eeeee 2010-06-27
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 ticmy 的回复:]

synchronized (this.beanFactoryMonitor)


好比桌子上有一个金牌

现在有一件事情,比如做饭,只有手持这块金牌的人才能做

我先把金牌拿走了,我有权利做饭

此时你也想做饭,你也去拿那块金牌,但是还在我手上,你只得等我把金牌放回来,也就是退出了ynchronized (this.beanFactoryMonitor) 块
[/Quote]
很形象,帮顶
「已注销」 2010-06-27
  • 打赏
  • 举报
回复
被synchronized括起来的对象就是一把钥匙。
这把钥匙能够开启所有使用该钥匙锁起来的代码块
但是该钥匙同时只能被一个线程拥有.

所有的对象,都可以当成锁。常见的this及XXX.class或者任意一个对象,都可以拿来当钥匙
fly2749 2010-06-27
  • 打赏
  • 举报
回复
他是不是只作为一个标记去限制线程共同访问代码块的呢?
lixkyx 2010-06-27
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 redduke1202 的回复:]

被synchronized括起来的对象就是一把钥匙。
这把钥匙能够开启所有使用该钥匙锁起来的代码块
但是该钥匙同时只能被一个线程拥有.

所有的对象,都可以当成锁。常见的this及XXX.class或者任意一个对象,都可以拿来当钥匙
[/Quote]

说得很准确。就是这样的。
fantasy471503202 2010-06-27
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 smh821025 的回复:]

beanFactoryMonitor,他是不是只作为一个标记去限制线程共同访问代码块的呢?
我只想知道这个答案,那如果真的是这样的话,那不如直接用this了,还有必要在该类中定义一个实例化对象作为参数么,这样有什么意义?
[/Quote]
synchronized(beanFactoryMonitor)并不是说限制线程访问共同的代码块儿,而是说此beanFactoryMonitor已经加上锁,如果是this就是指本对象已经加上锁,那么此对象中的一些数据或者方法的调用在一个时间段里只能被一个运行中的线程所拥有,其他线程只能等待。

括号中的对象并不仅仅是一个符号,而是你想对哪一个对象进行安全处理,那么就写哪个对象,当然参数可以不只是对象。
fly2749 2010-06-27
  • 打赏
  • 举报
回复
说的都很好,不知给谁分了
fly2749 2010-06-27
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 fantasy471503202 的回复:]
synchronized(beanFactoryMonitor)并不是说限制线程访问共同的代码块儿,而是说此beanFactoryMonitor已经加上锁,如果是this就是指本对象已经加上锁,那么此对象中的一些数据或者方法的调用在一个时间段里只能被一个运行中的线程所拥有,其他线程只能等待。

括号中的对象并不仅仅是一个符号,而是你想对哪一个对象进行安全处理,那么就写哪个对象,当然参数可以不只是对象。
[/Quote]
感谢,有些头绪了
fly2749 2010-06-27
  • 打赏
  • 举报
回复
beanFactoryMonitor,他是不是只作为一个标记去限制线程共同访问代码块的呢?
我只想知道这个答案,那如果真的是这样的话,那不如直接用this了,还有必要在该类中定义一个实例化对象作为参数么,这样有什么意义?
「已注销」 2010-06-27
  • 打赏
  • 举报
回复
一个锁,不止是控制不同线程运行同一段代码
也可以控制不同线程不能同时运行不同的代码
上面的比喻不全面
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 smh821025 的回复:]
引用 8 楼 lixkyx 的回复:
sychonized()里面的对象就是加锁的对象,如果它是this,那就是调用本方法的对象,如果是this.beanFactoryMonitor),那就是调用本方法的对象(this)的成员变量beanFactoryMonitor,它也是一个对象

我想知道的就是这个答案,beanFactoryMonitor是这个方法所在的类中的一个Object实例化对……
[/Quote]

是的,可以任意取名,也可以不是 Object 对象,弄个 String lockMonitor = ""; 之类也是可以的,因为每一个对象都有一个监视器。
fly2749 2010-06-26
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 lixkyx 的回复:]
sychonized()里面的对象就是加锁的对象,如果它是this,那就是调用本方法的对象,如果是this.beanFactoryMonitor),那就是调用本方法的对象(this)的成员变量beanFactoryMonitor,它也是一个对象
[/Quote]
我想知道的就是这个答案,beanFactoryMonitor是这个方法所在的类中的一个Object实例化对象,那么这个名字是不是可以随便起的呢,他是不是只作为一个标记去限制线程共同访问代码块的呢?
fantasy471503202 2010-06-26
  • 打赏
  • 举报
回复
很容易理解的。

首先应该知道的是,在上锁时,不管synchronized是加在一个类中的一个方法的前面或者是直接这样synchonized(this或者一个对象obj),一个对象只能加上一个锁。

第二点要知道的是,多个线程同时处于start状态,就拿楼主举例子中的那个方法来说吧,如果几个线程中的run()方法中都调用了refreshBeanFactory()这个方法,并且这个方法中有一个 synchronized(this.beanFactoryMonitor){}块儿,那么表示对这个beanFactoryMonitor对象上了锁,任何线程想要对这个对象(beanFactoryMonitor)中的方法进行执行就必须先获得beanFactory对象身上的这个锁,然后才能执行,此时这个对象就相当于一个上面有一个真实的锁,但是只有一个锁眼,每一个线程都有一把钥匙,一次只能有一个线程插入,只有等此线程钥匙拔出时,其他线程才能插入,这样就保证了对这个对象的操作时按时间流程顺序进行,保证了对其操作时的安全性。

归根结底,synchronized方法就是加上一个锁来防止多个线程同时对一个资源对象操作的方法,不知楼主明白没,再给楼主一个简单的例子更容易理解吧。

package a;

public class Count {
int num = 200;

public void count_num() {
this.num--;
}

public static void main(String args[]) {
Count c = new Count();
ThreadNum t1 = new ThreadNum(c);
ThreadNum t2 = new ThreadNum(c);
ThreadNum t3 = new ThreadNum(c);
ThreadNum t4 = new ThreadNum(c);
t1.start();
t2.start();
t3.start();
t4.start();
}
}

class ThreadNum extends Thread {
Count t_;
String name;

public ThreadNum(Count t) {
this.t_ = t;
}

public void run() {
while (true) {
synchronized (t_) {
this.name = Thread.currentThread().getName();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(t_.num > 0){
t_.count_num();

}else{
break;
}
System.out.println(this.name + " " + t_.num);
}
}
}
}

顺便给楼主一个自己的例子吧
lixkyx 2010-06-26
  • 打赏
  • 举报
回复
[Quote=引用楼主 smh821025 的回复:]
在spring的源码中,看到了关于synchronized的关键字的语句,但是对多线程的概念理解不是很清晰,所以想询问下高手。

Java code

protected final void refreshBeanFactory() throws BeansException {
// Shut down previous bean factory, if any.……
[/Quote]

sychonized()里面的对象就是加锁的对象,如果它是this,那就是调用本方法的对象,如果是this.beanFactoryMonitor),那就是调用本方法的对象(this)的成员变量beanFactoryMonitor,它也是一个对象。

这个语句的功能只是说明,从现在以后,任何一个线程想要执行sychonized块中的语句,必须先申请beanFactoryMonitor对象上的锁,如果别的线程已经得到了锁,那它就不可能执行sychonized块中的语句了。

至于哪个线程先获得这个锁,那要看程序的执行过程了,仅仅从你上面贴的这段代码中是看不出来的。
呼吸先生 2010-06-26
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 ticmy 的回复:]
“怎么样判断哪个线程可以得到这个对象的锁”

这个由jvm去管理,不用你管,不同公司的jdk可能有不同的实现
[/Quote]
说的对,线程的执行过程是我们不能干预的,JVM的规范其实说的也很笼统,有很多都是实现者自己去定义。
dracularking 2010-06-26
  • 打赏
  • 举报
回复
同步机制是围绕着一个内部实体内部锁(intrinsic lock)或监控锁(monitor lock)而建立的(API规范也经常简单地称这个实体为monitor)

内部锁参与了同步的两个功能:
实现了对对象状态的互斥访问
建立了对可见性至关重要的happens-before关系

每一个对象都有一个内部锁,beanFactoryMonitor不会例外,传统上,线程如果想要实现对对象域互斥且一致的访问就需要在访问对象域前去获得对象的内部锁,在访问结束后又释放内部锁。线程在获得锁和释放锁之间的时间里被称作拥有了内部锁。只要线程拥有着内部锁,其它线程就无法再拥有同一个锁,其它线程在想要尝试获得该锁时会阻塞。

当一个线程释放内部锁时,在释放动作与任何接下来的获得同一个锁的动作之间一个happens-before关系就会被建立。保证先于获得而释放,同时又建功于可见性。
thegodofwar 2010-06-26
  • 打赏
  • 举报
回复
http://lavasoft.blog.51cto.com/62575/27069
Java多线程编程总结
thegodofwar 2010-06-26
  • 打赏
  • 举报
回复
关于sleep和wait区别看一下这个: http://wurd.javaeye.com/blog/174563
thegodofwar 2010-06-26
  • 打赏
  • 举报
回复
关于synchronized可以看一下这篇:http://www.wangchao.net.cn/bbsdetail_148670.html,比较明了。
龙四 2010-06-26
  • 打赏
  • 举报
回复
“怎么样判断哪个线程可以得到这个对象的锁”

这个由jvm去管理,不用你管,不同公司的jdk可能有不同的实现
龙四 2010-06-26
  • 打赏
  • 举报
回复
synchronized (this.beanFactoryMonitor)


好比桌子上有一个金牌

现在有一件事情,比如做饭,只有手持这块金牌的人才能做

我先把金牌拿走了,我有权利做饭

此时你也想做饭,你也去拿那块金牌,但是还在我手上,你只得等我把金牌放回来,也就是退出了ynchronized (this.beanFactoryMonitor) 块

62,614

社区成员

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

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