锁定老帖子 主题:多线程开发,表示很凌乱
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2012-04-19
zfc827 写道
junlas 写道
嗯,非常感谢回复这么多,还是可以理解的。我把我的一个疑惑描述一下,可能有点2。有一种这样的情况,唯一的一个共享数据对象O,内部有方法A,方法B,起了5个线程去执行方法A,起了另外3个线程执行方法B,好的,请教,在方法A、B中: 1.访问对象O中的普通类变量需要synchronized,如果不是普通类变量,是java.util.concurrent包下的类型变量,就不用synchronized了,这点没错吧,如果没错,我理解的应该就没错。正如你上面所说。 2.方法A、B中的参数、临时变量,是否也需要synchronized?这是比较疑惑的了,我发帖的主要原因。我的理解是:线程1可能正执行到方法A、B的一半时,被切到线程2来执行这个方法,因为参数和临时变量没synchronized,这个值就变了??
我觉得是我肯定理解错了?求指点,如何理解呢 有几天没来看这个帖子了,可能我没说明白,楼主要明确,只有类变量有线程安全的问题!!!,方法中定义的临时变量,以及方法中传入的任何参数,都不存在线程安全问题!!! 线程执行1个方法时创建的所有临时变量都由线程自己维护,比如:2个线程执行同1个方法,那么创建的临时变量是2份,他们之间没有任何关系!!! 上面说法可能理解会有错误,楼主如果站在一个对象的内部来考虑线程安全,那么上面说法是正确的,但如果从类的外部来考虑,比如:如果一个方法的参数是一个对象,而多个线程调用该方法时传入的参数是同一个对象,那么这个对象确实不是线程安全的。这是由于参数的引用传递导致。我对线程的理解并没有深入到JVM实现中去,但是希望给楼主提供一个简单的思路去考虑线程安全。 下面举个例子:
public void run() { Model object = new Model(); object.changeMap1(); object.changeMap2(); } public class Model{ private static Map map1 = new HashMap(); private Map map2 = new HashMap(); public void changeMap1() { //.....change map1 } public void changeMap2() { //.....change map2 } } run方法中,他创建了一个Model对象。Model类中,定义有2个map和2个操作对应map的方法,其中map1是static的。楼主现在能判断这2个changeMap方法是不是线程安全的吗? 如果不能,以下是思路: 1、首先明确,类变量才有线程安全问题,在Model类内部,咋看之下这2个方法都不是线程安全的,因为他们都改变了类变量map的值。 2、但是跳出Model类,在run方法中,Model的实例object是run方法的一个临时变量,那么就发生了变化,多个线程执行run方法时,会创建多个Model对象,Model对象中的map2也会有多个且之间没有任何关系,所以changeMap2方法是线程安全的,因为他们根本不是访问的同一个map。 3、同理,虽然多线程也创建了多个Model对象,但是对map1而言,因为他是static的,map1只会创建一次!是单例的!,所有线程在调用changeMap1方法时都是访问同一个map,所以changeMap1不是线程安全的方法,需要加上synchronized关键字标识。 |
|
返回顶楼 | |
发表时间:2012-04-20
成员变量会有线程并发问题,局部变量和方法的参数是没有并发问题的。
|
|
返回顶楼 | |
发表时间:2012-04-20
关键是线程,线程的中断,以及涉及到线程与主线程之间的通信,比较麻烦,以及难以控制,多线程是梦靥
|
|
返回顶楼 | |
发表时间:2012-04-20
zfc827 写道
有几天没来看这个帖子了,可能我没说明白,楼主要明确,只有类变量有线程安全的问题!!!,方法中定义的临时变量,以及方法中传入的任何参数,都不存在线程安全问题!!! 线程执行1个方法时创建的所有临时变量都由线程自己维护,比如:2个线程执行同1个方法,那么创建的临时变量是2份,他们之间没有任何关系!!!
/** * 还是要看目标对象被并发使用的上下文有几个,跟是不是方法的local变量没关系吧 */ private void dummy() { //这是个方法内的本地变量吧? final AtomicInteger ai = new AtomicInteger(0); for (int i=0; i<10; i++) { ai.incrementAndGet(); new Thread() { public void run() { ai.decrementAndGet(); } }.start(); } System.out.println(ai);//等于几? } |
|
返回顶楼 | |
发表时间:2012-04-20
你这情况应该看NIO了吧。
|
|
返回顶楼 | |
发表时间:2012-04-20
atomduan 写道
zfc827 写道
有几天没来看这个帖子了,可能我没说明白,楼主要明确,只有类变量有线程安全的问题!!!,方法中定义的临时变量,以及方法中传入的任何参数,都不存在线程安全问题!!! 线程执行1个方法时创建的所有临时变量都由线程自己维护,比如:2个线程执行同1个方法,那么创建的临时变量是2份,他们之间没有任何关系!!!
/** * 还是要看目标对象被并发使用的上下文有几个,跟是不是方法的local变量没关系吧 */ private void dummy() { //这是个方法内的本地变量吧? final AtomicInteger ai = new AtomicInteger(0); for (int i=0; i<10; i++) { ai.incrementAndGet(); new Thread() { public void run() { ai.decrementAndGet(); } }.start(); } System.out.println(ai);//等于几? }说的没错,但是也只有这样类似闭包的写法才有问题,对于初学者而言,这种情况大多数都不作考虑。实际上对于run方法而言,ai就是一个单例对象。
|
|
返回顶楼 | |
发表时间:2012-04-23
最后修改:2012-04-23
zfc827 写道
atomduan 写道
zfc827 写道
有几天没来看这个帖子了,可能我没说明白,楼主要明确,只有类变量有线程安全的问题!!!,方法中定义的临时变量,以及方法中传入的任何参数,都不存在线程安全问题!!! 线程执行1个方法时创建的所有临时变量都由线程自己维护,比如:2个线程执行同1个方法,那么创建的临时变量是2份,他们之间没有任何关系!!!
/** * 还是要看目标对象被并发使用的上下文有几个,跟是不是方法的local变量没关系吧 */ private void dummy() { //这是个方法内的本地变量吧? final AtomicInteger ai = new AtomicInteger(0); for (int i=0; i<10; i++) { ai.incrementAndGet(); new Thread() { public void run() { ai.decrementAndGet(); } }.start(); } System.out.println(ai);//等于几? }说的没错,但是也只有这样类似闭包的写法才有问题,对于初学者而言,这种情况大多数都不作考虑。实际上对于run方法而言,ai就是一个单例对象。
嗯。。。 |
|
返回顶楼 | |
发表时间:2012-04-23
leu 写道
zfc827 写道
atomduan 写道
zfc827 写道
有几天没来看这个帖子了,可能我没说明白,楼主要明确,只有类变量有线程安全的问题!!!,方法中定义的临时变量,以及方法中传入的任何参数,都不存在线程安全问题!!! 线程执行1个方法时创建的所有临时变量都由线程自己维护,比如:2个线程执行同1个方法,那么创建的临时变量是2份,他们之间没有任何关系!!!
/** * 还是要看目标对象被并发使用的上下文有几个,跟是不是方法的local变量没关系吧 */ private void dummy() { //这是个方法内的本地变量吧? final AtomicInteger ai = new AtomicInteger(0); for (int i=0; i<10; i++) { ai.incrementAndGet(); new Thread() { public void run() { ai.decrementAndGet(); } }.start(); } System.out.println(ai);//等于几? }说的没错,但是也只有这样类似闭包的写法才有问题,对于初学者而言,这种情况大多数都不作考虑。实际上对于run方法而言,ai就是一个单例对象。
受教了,对于我而言,我还是会尽量避免这种写法。。 |
|
返回顶楼 | |
发表时间:2012-05-17
我的理解是,当两个以上线程共享并操作同一个变量时, 很容易发生原子性和一致性的问题,被共享的变量操作就需要进行同步,比如线程1进行i++同步时,线程2取得i就会等待,线程1操作结束线程2才开始操作i
|
|
返回顶楼 | |
发表时间:2012-05-18
aa87963014 写道 junlas 写道 aa87963014 写道 有2个方法操纵一个map对象,怎么实现线程安全?
2个方法都加上锁? 一般我都是用ConcurentHashMap这个对象 不是这个意思 多线程访问的时候,只需要对 共享的对象加锁。 操作共享对象的方法是不需要加锁的 还有一点就是:如果某个方法里面有多个共享对象,在方法加锁,是为了保证这个方法操作的原子性。 |
|
返回顶楼 | |