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--;
}
}
Run Code Online (Sandbox Code Playgroud)
谁能解释为什么上面的类不是线程安全的?
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();
Run Code Online (Sandbox Code Playgroud)
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对不同实例的两次重叠调用可能导致双重递减(正确)或单次递减.
| 归档时间: |
|
| 查看次数: |
9157 次 |
| 最近记录: |