public class Test {
List list= new java.util.ArrayList();
public void test() {
synchronized ( list) { // --A
list.add( String.valueOf(System.currentTimeMillis()));
}
}
}
A. test方法中必须增加synchronized
B. Test类为singleton时有必要增加synchronized
C. test方法中没有必要增加synchronized
D. Test类为singleton时也没有必要增加synchronized
答案就是B
A 如果Test类不是单例的话,那么list就是多个Test类里的多个实例list,所以加不加synchronized都是非线程安全的
B 对的,单例Test时,保证list也是唯一的实例对象,多线程访问test方法时,共同抢夺list这把对象监视锁。
C 与A解释相似,有没有必要看是否Test类是否单例
D 单例时,必要加上synchronized才能保证线程安全性。
A. test方法中必须增加synchronized
因为add操作不是线程安全的(不是原子化的),必须同步
c不用解释了。
和singleton没有关系。singleton只能保证私有成员是唯一的,不能保证线程安全。
首先楼主需要理解 类锁 和 实例锁
类锁:所有实例共享的锁 所有的实例 共享一把锁 ,
实例锁 :每个实例自己的锁 不同实例之间不影响
而楼主上面的 synchronized ( list) 就是对list这个实例加锁 是一个实例锁 所有对list这个实例的操作都需要获取锁
然后除非一个对象本身是线程安全的,不然对这个对象的操作都需要加锁 list就是非线程安全的
下面我们来分析答案:
首先我们排除答案c 不加锁的话 肯定是非线程安全的
当test为单例,言下之意就是list也是单例的 但是list是非线程安全的 所以必须加锁
当test为非单例,也就是说list为非单例,当多个线程对同一个test类的list进行操作 此时还是需要加锁
综上:答案A正确
你的问题关键在两点,同步synchronized和单例singleton
先说同步synchronized
同步其意义是为了确保动作的原子性(即动作一旦开始,不会被中途打断).
所以,它的存在就是为了解决动作可能被打断(多线程),但为了程序正确性某些动作不能被打断的问题
具体到程序,某段逻辑可能被多线程执行,但某次执行不应该被中断,否则会出错时,就需要对其加锁(如本例中synchronized)
再说单例singleton
单例其意义是为了确保某个类只能创建唯一对象(例如:你有一个数据库连接类,不需要同时存在多个连接,就可以使用单例)
换言之,同一个单例类使用的实例,无论在哪里,都是同一个
所以,这个问题的答案应该可以想清楚了吧
在你查询的地方,进行转换, 正常,异常,,,数据库存的是0,1代号, 转换成相应数字在查询就可以了。
CD不用想。B是正确的,但是A有一个问题,多线程操作同一个test(),那么要加synchronized。但是多线程操作不同的test()方法,那么就不用增加synchronized了
题意的关键是要保护ArrayList,该集合本身是非线程安全的。
然后要区分是类锁还是实例锁。简单来说锁的对象带了static关键字的就是类锁,没带就是实例锁;
比如说加在静态方法上的就是类锁,对所有实例有效,实例锁只对当前对象有效。就是作用范围不一样。
回到题目:如果是多个线程访问该类,但是为每个线程单独生成了实例,就像struts2 的Action,那么就无需加锁;
如果多个线程访问同一个Test类生成的实例,那么就需要保护。
我选择的答案是B
理由是:
当test类是多个实例的时候,Test类的list属性为各自每个Test类的,
把线程比喻做人,test类的list属性当做锁,实现的方法当做是test方法相当于关上门睡觉
当有二个线程访问时候,因为每个Test类都有各自的list属性,就相当二个人有各自的钥匙去自己的房间睡觉,此时并没有线程冲突问题
当Test类是单利的时候,list属性就是唯一的,相当于你们家卫生间的门,二个线程访问时候,就类似二个人为争夺卫生间使用权,争取到的人就可以到卫生间关上门上述锁 使用,只有当使用完卫生间的锁才会开,另一个人才可以去使用,此时就有线程安全的问题,就需要锁了
以上分析,选B
b