在以下示例中
以下是说明我的问题的示例代码:
BadDesign.java
public final class BadDesign{
private static int sensitiveData;
public synchronized static void changeDataViaStaticMethod(int a){
//... updating the sensitiveData
sensitiveData = a;
}
public synchronized void changeDataViaNonStaticMethod(int b){
//... updating the sensitiveData
sensitiveData = b;
}
public static void showSensitiveDataStatic(){
System.out.println("Static: " + Thread.currentThread().getName()+ " - " + sensitiveData);
}
public void showSensitiveData(){
System.out.println(Thread.currentThread().getName() + " - " + sensitiveData);
}
public static void main(String[] args){
new Thread(new TestThread11()).start();
new Thread(new TestThread11()).start();
}
}
和TestThread11.java
class TestThread11 implements Runnable{
public void run(){
int i = 0;
do{
BadDesign.changeDataViaStaticMethod(5);
BadDesign.showSensitiveDataStatic();
//... new object for every iteration
//... so synchronization of non-static method
//... doesn't really do anything significant here
BadDesign bd = new BadDesign();
bd.changeDataViaNonStaticMethod(10);
bd.showSensitiveData();
}while (i++ < 100);
}
}
答案 0 :(得分:6)
非静态版本将允许两个不同的线程通过不同的对象进入,获取不同的锁并仍然访问相同的共享数据。从根本上说,这不是线程安全的,并且基本上使锁无用。您希望一个锁定覆盖任何共享数据。
如果你真的想要,你仍然可以使用非静态方法(例如,如果结果应该部分地由实例数据确定),但你应该通过共享锁访问共享数据,例如
private static final Object staticLock = new Object();
...
synchronized (staticLock)
{
// Read or write static data
}
答案 1 :(得分:2)
do-while循环没有问题,如
BadDesign.changeDataViaStaticMethod(5); //needs BadDesign Class lock.
BadDesign.showSensitiveDataStatic(); //does not need any lock
和
bd.changeDataViaNonStaticMethod(10); // needs lock for bd object.
bd.showSensitiveData(); //does not need any lock
我希望能回答你的问题。
答案 2 :(得分:1)
我认为这是某种课程。这个特殊问题的重点似乎是强调Java中的两个基本基础
synchronized
如何隐式使用当前对象实例作为锁第1点是了解监视器的内容。我邀请您学习Java语言规范的相关部分Threads and Locks。监视器是线程可以锁定和解锁的东西。当一个线程锁定它时,试图锁定该特定监视器的任何其他线程将等待(阻塞)直到第一个线程解锁它。
第2点是关于Java中的编译器功能。当您指定某些内容为synchronized
而未明确指出要使用哪个监视器时,Java将使用被调用对象的实例。但是,如果该方法是静态的,它将使用对象类(java.lang.Class
)的实例作为监视器。这在现实中意味着什么?由于类加载器上下文中每个类对象只有一个唯一的全局实例,因此静态方法只有一个监视器。相反,实例方法将使用被调用的对象的实例作为监视器,因此每个对象将拥有它自己的监视器。 静态方法全局同步,实例方法针对该类的每个特定实例进行同步。