java - 仅检查一个条件的 while true 循环线程安全吗?

标签 java multithreading thread-safety primitive-types

我正在使用 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();
        }
    }
}

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

这可能是原因吗?我认为在处理多个线程时,原始数据类型并不是什么大问题(除非您正在检查 boolean 值,然后将其设置为阻止其他线程)。 Java 中的原始数据类型线程安全吗? (我什至无法同步它们,需要一个虚拟对象)

最佳答案

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

关于java - 仅检查一个条件的 while true 循环线程安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38703663/

相关文章:

java.lang.ClassCastException - 同一对象 - 两个类,为什么?

java - 我可以通过mysql触发器执行mysql之外的任何程序吗?

c++ - 使用来自 CreateFile 的有效句柄来自 ReadFileEx 的无效句柄错误

c# - 并发 XmlReader 和 XmlWriter

multithreading - WCF Operation.Context 不是线程安全的?

java - 我正在尝试插入 sql,但它一直给我错误

java - 在java代码中使用不同的压缩算法

java - 定时器已取消

C#,有没有 "thread-safe"流这样的东西?

java - 文件重命名时的线程安全