2012-09-06 116 views
12

考虑:制造类线程安全

public class TestSeven extends Thread { 

private static int x; 

public synchronized void doThings() { 
    int current = x; 
    current++; 
    x = current; 
} 

public void run() { 
    doThings(); 
    } 
} 

哪种说法是正确的? A.编译失败。

B.运行时抛出异常。 C.同步run()方法会使类是线程安全的。

D.变量“x”中的数据不受并发访问问题的影响。

E.声明的doThings()方法为静态会使类线程安全的。

F.结束语中doThings()中的同步(新的对象()){}块中的语句将使类线程安全的。

是不是足够的,为了使这个类线程安全的同步标记doThings()?我看到正确的答案是D,但这个问题的模型答案是E,但我不明白为什么?

回答

17

E.声明的doThings()方法为静态会使类线程安全的。

这是怎样的一个棘手的答案。该方法已经同步,但在实例上,而状态是在静态字段中,即在类上。使它static synchronized确实是正确的答案,因为它然后在类上同步,而不是在(无意义的)实例上同步。

D.变量“x”中的数据不受并发访问问题的影响。

private static int x; 

这是一个静态变量。它由类的所有实例共享,因此在单个实例上同步并不会有帮助,与F不会有帮助的方式相同,它可以在完全丢弃的虚拟对象上同步。

11

按照language spec

甲同步方法获取监视器它执行(§17.1)之前。

对于类(静态)方法中,使用与 Class对象方法的类相关联的显示器。

对于实例方法,与此相关的监视器(为其调用方法的对象 )被使用。

这意味着,在该代码时所提供的​​关键字使执行该方法的主体之前获取关于this锁的方法。但是,因为xstatic,所以不能确保更新到x将是原子。 (类的另一个实例可以进入同步区域并同时进行更新,因为它们具有不同的this值并因此具有不同的锁定。)

然而,声明doStuff静电会使该方法的所有调用获取同一锁(一对Class),因此将确保在方法体中相互排斥。

规格真的拼出的是:

class A { 
    static synchronized void doSomething() { 
     // ... 
    } 
} 

简直是一回事

class A { 
    static void doSomething() { 
     synchronized(A.class) { 
      // ... 
     } 
    } 
} 

同理:

class B { 
    synchronized void doSomething() { 
     // ... 
    } 
} 

简直是一回事

class B { 
    void doSomething() { 
     synchronized (this) { 
      // ... 
     } 
    } 
} 
6

通过同步doThings()方法,您可以保持特定TestSeven对象的锁定。但是,类的静态变量不属于对象本身的特定实例。它们属于类对象TestSeven.class。所以,要么你可以走了

synchronized (TestSeven.class){ 
    int current = x; 
    current++; 
    x = current; 
} 

您doThings内()方法,它正在收购一个实例的锁,矫枉过正的东西里面的类锁。因此,您可以将该方法标记为静态,以便最终获取单独的Class对象的锁定。

-6

我同意你说的正确答案是D. 我要说的是,E是不正确,因为如果我设置doThings()静态和删除synchronized关键字,我可以只启动50个TestSeven线程,则可能导致x值不正确。

注意: 我在这里错了,我错过了没有静态的同步方法实际上使用实例作为锁监视器而不是类本身的观点。

+3

D不正确。 – Keppil

+1

E是正确的,因为它不会说“删除同步关键字”。不必要的棘手措施,但这就是你在这些考试中得到的。 – Thilo

+0

D是正确的,因为使用给定的类没有其他方法来改变x的值。 如果允许添加其他方法,那么我会说甚至解决方案E是不正确的。 –

1

由于xstatic其他线程可以在同一时间修改它doThings方法正在运行。制作doThingsstatic将停止此操作。