-
一个多线程共享变量的问题,请教下大家15
工作中遇到了这么一个问题,想请教下大家。伪码如下:
public class AAAAA{ public boolean enable = true; // [b]非violate[/b] // 线程A执行 public void methodA{ while(enable){ ......... } system.out.println("----------------------"); } // 线程B执行 public void methodB{ enable = false; } }
前提:线程A和线程B一定都会执行code。
问题:线程A是否有可能会永远退不出循环?如果存在这种可能,请详细说明下原因,谢谢。
本人认为不会存在这种情况,但是有同事说存在这种可能,原因是JVM指令重排序优化。我查了些资料,没有找到充足的证据来证明此事,所以想在这里请教下各位大侠,先行谢过了。
问题补充:去掉活性失败的例子,如果MethodA的实现变更为
public void methodA{
while(true){
dosomething();
if (enable){
dosomething();
}
dosomething();
}
}
那么enable也会永远为true吗?2012年7月30日 00:13
15个答案 按时间排序 按投票排序
-
采纳的答案
看看effective java 中文版第二版 230页 如果没错的话 这个描述叫做火星失败 liveness failure 是因为 while(enable) 被jvm 优化成 if(!enable) {
while (true)
} 所以需要设置同步访问 或者是 在enable 前 加上 violate 这样 当enable变化时 这样他能保证任何一个线程在读取该域的时候能看见最新被修改的值
以上全是引用书中的话 若有不全的地方 请看书籍2012年7月30日 12:18
-
当有多个线程同时来存取某一个对象时,就出现可见性问题.
为了保证变量的可见性,一般可以用锁、 synchronized关键字、 volatile关键字或直接设置为final ;
线程在MethodA 方法中,只是一次从寄存器读取进来,一直没有改变变量enable的值,一般不会主动更新主存的值到工作内存中,所以很有可能一直下去.2012年7月31日 15:49
-
昨天可能没有理解你的意思。后来想了想,这里跟JVM指令重排没有关系的,如果有A线程和B线程同时操作AAAA,但是至于A会不会退出循环,跟A线程和B线程执行的具体情况而定,假如线程B已经执行完了methodB,而且修改的enable对线程A可见,那么A就退出循环了。
加上volatile主要是保证修改值后对另外的线程可见。这样可以保证线程间的同步,但是并不意味着不加volatile就不能实现同步,只是发生的事件是一个概率事件。也就是说线程A同样可以拿到线程B已经修改的enable的值。
最后的结论是:这里讨论线程A是否有可能会永远退不出循环意义不大。因为这个事件本身是不确定事件。只有线程B执行完methodB后且修改enable值对线程A可见,而线程A执行methodA,这样就退出循环。是一个概率事件。如果非要对你那个下结论的话我觉得"不可能",既然是概率事件当样本足够多的话总会发生的。
希望我的回答能帮到你2012年7月31日 08:03
-
跟“指令重排序优化”无关,两个线程读取的enable可能是不同的,为了优化执行变量可能在cpu缓存里有副本,cpu缓存也是多级的,再加上内存里的副本,不一定读到的是哪个
可以给 enable加 volatile修饰 一种弱强制同步2012年7月30日 15:53
-
if (enable){
dosomething();
}
如果你这个dosomething显示执行methodB,然后将enable = true;
这样就可以实现线程A一直循环下去了2012年7月30日 15:53
-
如果你的2个线程是共享一个AAAAA对象的话,那是必定会退出循环的,2个线程共享的是相同的对象,同一个内存地址,线程B如果改变了enable的地址值,那么线程A的调用的methodAwhile循环条件就变成了false,那就退出了循环。
2012年7月30日 14:52
-
可能的,原因是enable不是同步即时的(即你说的非violate的),然后线程A就会看不到enable的变化,就一直不断的执行while代码
2012年7月30日 11:44
-
程序的本意是希望methodB中断methodA,但是,由于编译器判断在methodA里面没有修改过enable ,因此可能只执行一次对enable 到某寄存器的读操作,然后每次if判断都只使用这个寄存器里面的“enable 副本”,导致循环永远无法退出,如果将enable加上volatile修饰,则编译器保证对此变量的读写操作作都不会被优化(肯定执行),那么当methodB执行完后,methodA即可退出循环。
2012年7月30日 11:31
-
首先,你确定你同一个AAAAA的对象被A,B线程同时操作了,才会出现线程问题。
假如是的话,除非B线程没有执行到,那么可能会一直执行下去,基本上不太可能,线程B总会改变这个enable。
但是假如说:methodA和methodB都加上同步锁,出现的可能性就极大了。2012年7月30日 11:12
相关推荐
一、题目: 创建线程,利用互斥实现线程共享变量通信 二、目的 掌握线程创建和终止,加深对线程和进程概念的理解,会用同步与互斥方法实现线程之间的通信。 三、内容和要求 软件界面上点“创建线程” 按钮,创建三个...
一个简单记录java多线程下变量共享问题,分析多线程内部运行
C#多线程互斥实例 多线程获取同一变量(不重复)。是一个很好的学习例子
1.Qt下,多线程使用互斥锁安全访问同一全局变量;2.源码中定义了ThreadA和ThreadB,定义变量后,依次调用函数start()来启动重写的run()函数
NULL 博文链接:https://toknowme.iteye.com/blog/2212529
此代码采用直接给线程变量赋值不需要参数传递
本文主要是对C语言多线程中变量累加问题进行分析,感性趣的朋友可以参考下。
Python写的多线程共享全局变量代码,用于学习多线程开发,可以直接运行,并且带中文注释,方便初学者学习使用。
1.使用三种VC的多线程同步方法编写一个多线程的程序(要求在屏幕上先显示Hello,再显示World)。 1)基于全局变量的多线程同步程序; 2)基于事件的多线程同步程序; 3)基于临界区的多线程同步程序。
多线程不同步读写共享资源 文章配套代码 我在很早的时候就听说多线程不同步是可以...写线程判断条件 if(下一个指针==读线程指针) 其实这就是一简单的生产者与消费者问题。 以下是实现方法 共享资源 我使用循环缓冲区
今天没事给大家写一个多线程例子 今天没事给大家写一个多线程例子
java 多线程 加减变量
通过改变全局变量实时改变目标变量的做法,比如这里,楼主也就是我,为了在树莓派上运行一个tcp结构的客户端线程,并通过摄像头线程收集的数据实时的通过tcp客户端线程处理并发回服务端(这是只对两个线程间的数据传递,多...
适合linux-c网络编程初学者学习的多线程控制,linux下编译通过,通过互斥锁和条件变量,最终线程的运行结果输出到txt文件中。
即使用一个两个线程都能够共享的变量(如全局变量),这样两个线程都能够访问和修改该变量,从而达到共享数据的目的。 2)使用singal/slot机制,把数据从一个线程传递到另外一个线程。 代码中是针对信号和槽机制,...
采用全局变量方式实现多线程的通信:用一个全局变量来控制时间显示线程的时间显示格式,比较简单,仅供参考和学习,欢迎大家多多交流。
python多线程可以使任务得到并发执行,但是有时候在执行多次任务的时候,变量出现“意外”。 import threading,time n=0 start=time.time() def b1(num): global n n=n+num n=n-num def b2(num): for i in ...
java 多线程 其实就是每个线程都拥有自己的内存空间,多线程之间的通信,比例A线程修改了主内存(main方法的线程)变量,需要把A线程修改的结果同步到主线程中,这时B线程再从主线程获取该变量的值,这样就实现了...
该文件中实例说明了如何在Labwindows/cvi中使用线程锁和线程安全变量进行多线程程序设计