为什么这段代码不是“线程安全的”?

时间:2018-04-24 16:11:35

标签: java thread-safety

class ThreadUnsafe 
{ 
    static int  val1,  val2; 
    static void Go()
    { 
        if  (val2 != 0)  System.out.println( val1 / val2); 
        val2=0; 
    } 
} 

显然,此代码中的Go()方法不被视为"线程安全"。这是为什么?

1 个答案:

答案 0 :(得分:0)

通常在Java中,当并发预期成为问题时,synchronized关键字将用于更改或读取对象内部状态的方法,或者synchronized块将用于锁定非null对象。两者都需要创建访问器方法来设置val1和val2的值。

使用synchronized更改(或读取)内部状态的示例:

class ThreadSafe
{
    private static int val1;
    private static int val2;

    static synchronized void go()
    {
        if (val2 != 0)
        {
            System.out.println(val1 / val2);
        }

        val2 = 0;
    }

    static synchronized void setVal1(int newVal1)
    {
        val1 = newVal1;
    }

    static synchronized void setVal2(int newVal2)
    {
        val2 = newVal2;
    }
}

在这种情况下,因为方法是静态的,所以同步将在类本身上发生。

在非null对象上使用同步的示例:

class ThreadSafe
{
    private static int val1;
    private static int val2;

    private static Object lock = new Object();

    static void go()
    {
        synchronized (lock)
        {
            if (val2 != 0)
            {
                System.out.println(val1 / val2);
            }

            val2 = 0;
        }
    }

    static void setVal1(int newVal1)
    {
        synchronized (lock)
        {
            val1 = newVal1;
        }
    }

    static synchronized void setVal2(int newVal2)
    {
        synchronized (lock)
        {
            val2 = newVal2;
        }
    }
}

另见What does 'synchronized' mean?