synchronized 的问题

funnyone 2012-02-11 09:52:50

public class AttributesStore {
private HashMap usersMap = new HashMap();
private HashMap servicesMap = new HashMap();
public synchronized void setUserInfo(String user, UserInfo userInfo) {
usersMap.put(user, userInfo);
}
public synchronized UserInfo getUserInfo(String user) {
return usersMap.get(user);
}
public synchronized void setServiceInfo(String service,
ServiceInfo serviceInfo) {
servicesMap.put(service, serviceInfo);
}
public synchronized ServiceInfo getServiceInfo(String service) {
return servicesMap.get(service);
}
}




这里,用户和服务数据的访问器方法是同步的,这意味着它们在 AttributesStore 对象上同步。虽然这样做是完全线程安全的,但却增加了毫无实际意义的争用可能性。如果一个线程正在执行 setUserInfo ,就不仅意味着其它线程将被锁在 setUserInfo 和 getUserInfo 外面(这是我们希望的),而且意味着它们也将被锁在 getServiceInfo 和 setServiceInfo 外面。

而且意味着它们也将被锁在 getServiceInfo 和 setServiceInfo 外面。 为甚麽会这样呢
,是方法锁 而不是对象锁



原文 http://www.ibm.com/developerworks/cn/java/j-threads/index2.html
...全文
164 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
coolhty 2012-02-19
  • 打赏
  • 举报
回复
还有一个简单的办法

private HashMap usersMap = Collections.synchronizedMap(new HashMap());
private HashMap servicesMap = Collections.synchronizedMap(new HashMap());

创建同步Map,也可以解决楼主问题,因为同步的方法体内没有其他需要同步的数据,同步Map也是一样的。
coolhty 2012-02-19
  • 打赏
  • 举报
回复

public class AttributesStore {
private HashMap usersMap = new HashMap();
private HashMap servicesMap = new HashMap();
public void setUserInfo(String user, UserInfo userInfo) {
synchronized(usersMap){//为什么不这样,就可以各锁各了..操作usersMap的时候同时可以操作servicesMap
usersMap.put(user, userInfo);
}
}
....
}

jsjszg 2012-02-19
  • 打赏
  • 举报
回复
一个线程访问该象的一个synchronized方法时,其他线程不能访问该对象的其他synchronized方法,而该对象的非synchronized方法是没有影响,多个线程仍然可以自由进入非synchronized的方法。

其实你要锁的是usersMap 和servicesMap ,完全没必要再方法上加同步。
jhzhu_android 2012-02-18
  • 打赏
  • 举报
回复
对象锁的概念,就是这个锁是属于这个当前对象的,某个线程调用同步方法,就必须获得这个对象的锁,而每个对象只拥有一把锁,所以当有线程获得当前对象的锁时,其他线程都得等待获得锁的线程释放这个对象的锁,即在锁池中等待。
爱摸鱼de老邪 2012-02-11
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 jiakai0419 的回复:]

楼上preferme已经说的好了。

我在这里再赘述一下。

首先,所有的锁都是加载对象上的。

即使是同步方法也是如此,只不过同步方法是锁的this

相当于
Java code

public void synchronized deal(){
synchronized(this) {
//代码块
}
}




如果一个线程获取了某个……
[/Quote]
你这个说法是错误的,楼主查看的网页的说法是对的。一个线程访问该象的一个synchronized方法时,其他线程不能访问该对象的其他synchronized方法,而该对象的非synchronized方法是没有影响,多个线程仍然可以自由进入非synchronized的方法。你可以写个例子验证。
楼主可以看看《Java并发编程》。我对该段话的理解是:因为该类所有的方法都是synchronized,实际上就等同于在这个类的实例对象上进行同步。这种写法加大了同步锁的粒度。正如它在里面所说的,实际上,我们希望能够自由访问get方法,而只对set方法进行限制。至于为什么一个时间只允许一个线程访问synchronized方法,我也不太清楚,也许是语言本身规定。期待有人讲解它的意义。
jiakai0419 2012-02-11
  • 打赏
  • 举报
回复
楼上preferme已经说的好了。

我在这里再赘述一下。

首先,所有的锁都是加载对象上的。

即使是同步方法也是如此,只不过同步方法是锁的this

相当于

public void synchronized deal(){
synchronized(this) {
//代码块
}
}



如果一个线程获取了某个对象的锁。

那么其他线程想获取该对象锁的时候,就会阻塞。

阻塞在该对象的阻塞队列上。
冰思雨 2012-02-11
  • 打赏
  • 举报
回复
方法锁和对象锁,没听说过这个概念。
楼主,例子中的synchronized 关键字,它的锁,是所在具体AttributesStore类的一个实例上面的。

加锁的目的,是为了保护两个内置对象usersMap 和servicesMap 的线程安全。

优点:无论调用对象的哪个方法,受保护的2个内置对象,它的数据都会是一致的。
缺点:由于两个内置对象使用了同一个锁,那么,你在访问其中一个对象的同时,
其它线程是无法访问另一个对象的。

“被所在 ... 外面”就是上述的缺点。

62,615

社区成员

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

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