java吧 关注:1,299,139贴子:12,837,608
  • 63回复贴,共1

请教一个多线程的问题,这段java多线程代码为什么后来不输出东西

只看楼主收藏回复

public class Test4
{
private static boolean b;
private static int count = 0;
public static void main(String[] args)
{
new Thread(() -> {
while (true){
count++;
if(b == !b){
System.out.println(new Date()+":"+count);
}
}
}).start();
new Thread(() -> {
while (true)
{
b=!b;
}
}
).start();
}
}
上面这段代码,第一个线程比较b和!b,第二个线程不断改变b的值,
讲道理的话,如果“取出第一个b”和“取出第二个b”这两个行为发生
在第二个线程改变b之前和之后,这时候b==!b条件是成立的。
这个程序会不断地输出count的值,
但是事实上,这段代码在输出一段时间之后,就不会输出了,
也就意味着这段代码只有一开始的时候会发生 b==!b这样的事情,
后来这件事情就再也不发生了,
本人对此感到不解,请各位大佬解惑。
另外,如果把b修饰为volatile ,那么就会一直输出下去。


IP属地:浙江1楼2017-02-04 11:07回复
    来人回答一下


    IP属地:浙江2楼2017-02-04 11:09
    回复
      2026-03-11 02:46:12
      广告
      不感兴趣
      开通SVIP免广告
      啊?


      IP属地:浙江4楼2017-02-04 11:10
      回复
        线程是不是设置权重,都是5应该可以


        IP属地:山东来自Android客户端5楼2017-02-04 11:11
        收起回复
          由于jvm即时编译器会对内存进行优化,线程2修改b的值线程1并不会马上知道;而使用了volatile后会禁止代码重排序,效果是线程2改变b的值线程1会马上知道


          IP属地:广东来自Android客户端7楼2017-02-04 11:38
          收起回复
            好奇怪啊,我跑了一下代码,把b声明成 private volatile boolean,居然也有一些时候会输出count


            IP属地:四川来自Android客户端8楼2017-02-04 13:20
            收起回复
              线程有自己的工作内存,而静态变量是在堆内存里(主存),线程要使用到某个堆内存里的值时,是拷贝一份副本到工作内存里再使用的,所以你不使用volatile修饰b,可能2个线程都用的是副本的旧值,另一个线程即使修改了b的值,另一个线程也无法感知(因为没有去主存内获取最新的值)


              IP属地:浙江9楼2017-02-04 14:07
              收起回复

                @du受爱Goo攻


                IP属地:浙江10楼2017-02-04 15:41
                回复
                  2026-03-11 02:40:12
                  广告
                  不感兴趣
                  开通SVIP免广告

                  @du受爱Goo攻 现在已经输出了很久了,int都越界了。


                  IP属地:浙江11楼2017-02-04 15:44
                  回复
                    刚才试了一下,给jvm指定参数-Djava.compiler=NONE禁用JIT编译就可以不停的输出,说明确实是jit的锅,估计和jit的代码提升等优化有关,想用参数-XX:+PrintOptoAssembly看下jit编译过后的代码发现debug版本的jvm才可以,楼主可以试下或是去知乎问下R大


                    IP属地:辽宁来自iPhone客户端12楼2017-02-04 16:00
                    收起回复