关于使用synchronized(localvar)的问题.

逗泥丸的平方 2018-07-24 01:52:16
我定义了一个Map<String,List>的数据结构,由于担心List中的同步问题,使用了Collections.synchronizedList(List)
并且遵从他的建议:

返回指定列表支持的同步(线程安全的)列表。为了保证按顺序访问,必须通过返回的列表完成所有对底层实现列表的访问。
在返回的列表上进行迭代时,用户必须手工在返回的列表上进行同步:


List list = Collections.synchronizedList(new ArrayList());
...
synchronized(list) {
Iterator i = list.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}


但是当我把代码写好了之后,编译器却警告我:synchronization on local variable or method parameter

我是否应该忽略这个警告呢?使用一个本地变量来进行同步是不妥当的?有没有一些折中的方式来解决这一问题呢?
...全文
5239 5 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
stacksoverflow 2018-07-24
  • 打赏
  • 举报
回复
引用 4 楼 qq_35209952 的回复:
[quote=引用 3 楼 stacksoverflow 的回复:]
[quote=引用 2 楼 qq_35209952 的回复:]
谢谢. 我的这个类是一个单例,这个Map<String,List>是一个类成员变量.这样的前提是否可以认为已经回避了这种情况?
之所以这样使用,是因为这个list的内容会在一个监听器中被改变,那边可能是多线程的.

每太看懂,参照下面的解释,或许能解决你这个疑问。

引用 2 楼 qq_35209952 的回复:
sync(obj)只要保证obj在内存中是同一个对象就可以达成同步的吧?

对,sync(obj)是对实例的同步,只要保证是同一个对象就可以达成同步。
展开一下:类的方法在方法区只有一份,new多个实例后,就变成了堆内存中有多个实例(类变量放在堆内存),但是都指向方法区的同一个方法。
所以就出现了sync(obj),sync(class)等写法来同步特定实例,或者同步整个类型。
[/quote]

我的意思大概就是,我可以保证这个list对象的生命周期以及唯一性. 所以在局部使用synchronized(list)应该是没有风险的吧.
当然这可能会导致可读性下降,但是没有想到一个更好的替代方法.[/quote]
对,这个没问题。
逗泥丸的平方 2018-07-24
  • 打赏
  • 举报
回复
引用 3 楼 stacksoverflow 的回复:
[quote=引用 2 楼 qq_35209952 的回复:]
谢谢. 我的这个类是一个单例,这个Map<String,List>是一个类成员变量.这样的前提是否可以认为已经回避了这种情况?
之所以这样使用,是因为这个list的内容会在一个监听器中被改变,那边可能是多线程的.

每太看懂,参照下面的解释,或许能解决你这个疑问。

引用 2 楼 qq_35209952 的回复:
sync(obj)只要保证obj在内存中是同一个对象就可以达成同步的吧?

对,sync(obj)是对实例的同步,只要保证是同一个对象就可以达成同步。
展开一下:类的方法在方法区只有一份,new多个实例后,就变成了堆内存中有多个实例(类变量放在堆内存),但是都指向方法区的同一个方法。
所以就出现了sync(obj),sync(class)等写法来同步特定实例,或者同步整个类型。
[/quote]

我的意思大概就是,我可以保证这个list对象的生命周期以及唯一性. 所以在局部使用synchronized(list)应该是没有风险的吧.
当然这可能会导致可读性下降,但是没有想到一个更好的替代方法.
stacksoverflow 2018-07-24
  • 打赏
  • 举报
回复
引用 2 楼 qq_35209952 的回复:
谢谢. 我的这个类是一个单例,这个Map<String,List>是一个类成员变量.这样的前提是否可以认为已经回避了这种情况?
之所以这样使用,是因为这个list的内容会在一个监听器中被改变,那边可能是多线程的.

每太看懂,参照下面的解释,或许能解决你这个疑问。

引用 2 楼 qq_35209952 的回复:
sync(obj)只要保证obj在内存中是同一个对象就可以达成同步的吧?

对,sync(obj)是对实例的同步,只要保证是同一个对象就可以达成同步。
展开一下:类的方法在方法区只有一份,new多个实例后,就变成了堆内存中有多个实例(类变量放在堆内存),但是都指向方法区的同一个方法。
所以就出现了sync(obj),sync(class)等写法来同步特定实例,或者同步整个类型。
逗泥丸的平方 2018-07-24
  • 打赏
  • 举报
回复
引用 1 楼 stacksoverflow 的回复:
同步局部变量是没有意义的,局部变量在CPU执行到该方法的时候压栈,出方法的时候出栈,
不存在多个线程同时访问一个局部变量的情况。

你把list放到类变量里,就会有多个线程同时访问类变量的同步访问的情况了。(类变量存在堆内存中)


谢谢. 我的这个类是一个单例,这个Map<String,List>是一个类成员变量.这样的前提是否可以认为已经回避了这种情况?
之所以这样使用,是因为这个list的内容会在一个监听器中被改变,那边可能是多线程的.

sync(obj)只要保证obj在内存中是同一个对象就可以达成同步的吧?
stacksoverflow 2018-07-24
  • 打赏
  • 举报
回复
同步局部变量是没有意义的,局部变量在CPU执行到该方法的时候压栈,出方法的时候出栈,
不存在多个线程同时访问一个局部变量的情况。

你把list放到类变量里,就会有多个线程同时访问类变量的同步访问的情况了。(类变量存在堆内存中)

67,550

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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