并发执行静态和非静态同步方法的问题?

时间:2011-08-01 06:37:12

标签: java

在以下示例中

  1. 如果不同的线程试图访问静态和 非静态同步方法同时进行,并依次尝试 使用两种方法更改静态数据?
  2. 使用run()方法的do-while循环是否有任何问题 为每个非静态创建BadDesign类的新对象 同步方法调用?
  3. 这个Java代码是否正确同步?
  4. 以下是说明我的问题的示例代码:

    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);
        }
    }
    

3 个答案:

答案 0 :(得分:6)

非静态版本将允许两个不同的线程通过不同的对象进入,获取不同的锁并仍然访问相同的共享数据。从根本上说,这不是线程安全的,并且基本上使锁无用。您希望一个锁定覆盖任何共享数据。

如果你真的想要,你仍然可以使用非静态方法(例如,如果结果应该部分地由实例数据确定),但你应该通过共享锁访问共享数据,例如

private static final Object staticLock = new Object();

...

synchronized (staticLock)
{
    // Read or write static data
}

答案 1 :(得分:2)

  1. 多个线程访问的静态和非静态数据由不同级别的锁处理。访问非静态方法的线程共享对象级别锁定(每个对象),访问静态方法需要类级锁定(每个类1个)
  2. do-while循环没有问题,如

       BadDesign.changeDataViaStaticMethod(5); //needs BadDesign Class lock.     
       BadDesign.showSensitiveDataStatic();  //does not need any lock 
    
  3.        bd.changeDataViaNonStaticMethod(10); // needs lock for bd object.
           bd.showSensitiveData();              //does not need any lock 
    

    我希望能回答你的问题。

答案 2 :(得分:1)

我认为这是某种课程。这个特殊问题的重点似乎是强调Java中的两个基本基础

  1. 任何对象都可以作为Java中的监视器
  2. synchronized如何隐式使用当前对象实例作为锁
  3. 第1点是了解监视器的内容。我邀请您学习Java语言规范的相关部分Threads and Locks。监视器是线程可以锁定解锁的东西。当一个线程锁定它时,试图锁定该特定监视器的任何其他线程将等待(阻塞)直到第一个线程解锁它。

    第2点是关于Java中的编译器功能。当您指定某些内容为synchronized而未明确指出要使用哪个监视器时,Java将使用被调用对象的实例。但是,如果该方法是静态的,它将使用对象java.lang.Class)的实例作为监视器。这在现实中意味着什么?由于类加载器上下文中每个类对象只有一个唯一的全局实例,因此静态方法只有一个监视器。相反,实例方法将使用被调用的对象的实例作为监视器,因此每个对象将拥有它自己的监视器。 静态方法全局同步,实例方法针对该类的每个特定实例进行同步。