das*_*der 94 java multithreading thread-safety
class ThreadSafeClass extends Thread
{
     private static int count = 0;
     public synchronized static void increment()
     {
         count++;
     }
     public synchronized void decrement()
     {
         count--;
     }
}
谁能解释为什么上面的类不是线程安全的?
K E*_*son 134
由于该increment方法是static它将在类对象上同步ThreadSafeClass.该decrement方法不是静态的,将在用于调用它的实例上同步.即,它们将在不同对象上同步,因此两个不同的线程可以同时执行这些方法.由于++和--操作不是原子的,因此类不是线程安全的.
此外,由于count就是static,从修改它decrement是一种同步的实例方法是不安全的,因为它可以在不同的情况下被调用和修改count同时的方式.
Sli*_*imu 23
您有两个同步方法,但其中一个是静态的,另一个不是.访问同步方法时,根据其类型(静态或非静态),将锁定另一个对象.对于静态方法,锁定将放在Class对象上,而对于非静态块,锁定将放在运行该方法的类的实例上.因为您有两个不同的锁定对象,所以可以有两个线程同时修改同一个对象.
Jea*_*ard 14
谁能解释为什么上面的类不是线程安全的?
increment 静态,同步将在类本身上完成.decrement如果不是静态的,则会在对象实例化上完成同步,但这不会像count静态那样保护任何内容.我想补充一点来声明一个线程安全的计数器,我相信最简单的方法是使用AtomicInteger而不是原始的int.
让我将您重定向到java.util.concurrent.atomicpackage-info.
其他人的答案很好地解释了原因.我只是添加一些内容来总结synchronized:
public class A {
    public synchronized void fun1() {}
    public synchronized void fun2() {}
    public void fun3() {}
    public static synchronized void fun4() {}
    public static void fun5() {}
}
A a1 = new A();
synchronizedon fun1和fun2在实例对象级别上同步.synchronizedon fun4在类对象级别上同步.意思是:
a1.fun1()时,后一个呼叫将被阻止.a1.fun1()和线程2同时呼叫a1.fun2()时,后一个呼叫将被阻止.a1.fun1()和线程2同时调用a1.fun3(),没有阻塞时,这两个方法将同时执行.A.fun4(),如果其他线程调用A.fun4()或A.fun5()同时调用,后面的调用将被阻止,因为synchronizedon fun4是类级别.A.fun4(),线程2同时调用a1.fun1(),没有阻塞,这两个方法将同时执行.decrement是锁定不同的东西,increment所以他们不会阻止彼此运行.decrement一个实例是锁定一个不同的东西来调用decrement另一个实例,但它们正在影响同样的事情.第一个意味着重叠调用increment并decrement可能导致取消(正确),增量或减量.
第二个意味着decrement对不同实例的两次重叠调用可能导致双重递减(正确)或单次递减.