是真正的循环只检查一个条件线程是否安全?

时间:2016-08-01 16:23:47

标签: java multithreading thread-safety primitive-types

我正在使用一个正在检查条件变为true的while循环:

while(Game.gameState != Game.CLOSING)
{
    if(reconnecting)
    {
        time = System.currentTimeMillis();
    }
    else
    {
        while(time + desiredWait > System.currentTimeMillis())
        {
            try{Thread.sleep(5);}catch(InterruptedException e){}
        }

        time += desiredWait;
    }

    synchronized (Game.gameStateLock)//added to circumvent the problem
    {
        if(Game.gameState == Game.INPROGRESS)//problematic condition
        {
            while(true)
            {
                synchronized (Lockstep.nextTurns)
                {
                    if(!Lockstep.nextTurns.isEmpty() || lockstep.currentTurn == 0)
                        break;
                }

                try{Thread.sleep(5);}catch(InterruptedException e){}

                time = System.currentTimeMillis();
            }

            Lockstep.attemptTurn();
        }
    }
}

循环不间断地运行(如果重新连接为真),因此在每个循环中访问Game.gameState(类型为int)两次。如果现在在第二个线程(例如,通过网络)中更改了gameState,则while循环/ if条件不检测它并继续拒绝执行if块中的代码,即使它应该。添加的synchronized(Game.gameStateLock)解决了这个问题。它也很难调试,导致打印gameState或其他任何东西都会导致问题不存在。我的猜测是I / O中断/休眠线程或导致它写入/读取那么多数据,cpu的缓存被清除,并且从缓存中读取的gameState变量必须从整个时间重新加载RAM。

这可能是原因吗?我假设原始数据类型在处理多个线程时没有那么多问题(除非你检查一个布尔值,然后将其设置为阻止其他线程)。 Java线程中的原始数据类型是否安全? (我甚至无法同步它们,需要一个虚拟对象)

2 个答案:

答案 0 :(得分:2)

"线程安全"这不是你正在寻找的术语,这可能就是你为什么挣扎的原因。您的代码在技术上是“线程安全的”,因为多线程导致您不会遇到任何损坏。然而,你所缺少的是与#34;可见性相关的保证"。在您的情况下,无法保证一个线程所做的更改将是"可见"到另一个。有多种方法可以使变化可见。在您的情况下,使gameState volatile变得足以强制跨线程查看对该值的更改。

答案 1 :(得分:-1)

原始类型不是线程安全的!检查一下:http://i-proving.com/2009/04/23/java-primitive-thread-safety/?showComments=true