2011-08-01 43 views
4

在下面的例子并发执行静态和非静态同步方法的问题?

  1. 如果不同的线程试图同时访问静态和 非静态同步方法,进而尝试 改变使用两种方法中的静态数据会发生什么?
  2. 使用run()方法的do-while循环到 是否有任何问题为每个非静态的 同步方法调用创建类BadDesign的新对象?
  3. 此Java代码是否正确同步?

下面是示例代码说明我的问题:

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

我很累,很早在早上编辑一篇文章。我会让其他敏锐的编辑出现并占据这个堡垒。 ;-) –

+0

@The精英绅士 - 你们不睡觉:P。考虑编辑它。 – Perception

回答

2
  1. 由多个线程存取的静态和非静态数据是由不同的电平的锁处理。该访问非静态方法的线程共享的对象级锁(也就是每对象),其中作为访问静态方法,你需要一流水平锁(这是1元类)
  2. 没有与DO-而没有问题环路,如

    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 

我希望回答你的问题。

+1

好..谢谢你..所以上面的代码是否合适synchoronised或没有好的 – chinchu

+0

ahh..ok。您在showSensitiveData()中编写的代码永远不会线程安全。这意味着多个线程可以同时访问这个方法,因为它不同步。所以如果你写了类似的东西,递增一些全局值,并期望它在每个线程中显示正确的值,那么可能会忽略该情况。 – Swagatika

6

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

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

private static final Object staticLock = new Object(); 

... 

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

@chinchu:你什么意思?我已经表明你必须使用同步语句。你的意思是使用同步*方法*?如果是这样,我会亲自避免那些开始 - 避免暴露你的锁,除非你真的必须。 –

+1

Yah先生....你是正确的.. :-)我的意思是使用同步的method.okay! – chinchu

+0

@chichu:正确 - 同步方法基本上等价于在其中有'synchronized(this)'或'synchronized(TheDeclaringClass.class)'语句。不是一个好主意,因为锁定在同一监视器上的任何其他人都可能导致死锁。 –

1

我假设这是某种课程。看来这个特殊问题的关键是要突出两个基本的基础知识的Java

  1. 任何对象都可以作为显示器中的Java
  2. 如何​​隐式使用当前对象实例的锁

第一点是关于理解监视器是什么。我邀请您学习Java语言规范的相关部分,Threads and Locks。显示器是一个线程可以解锁。当一个线程锁定它时,任何试图锁定该特定监视器的其他线程都会等待(阻止),直到第一个线程解锁它。

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