Jav*_*yer 14 java synchronization thread-safety
鉴于:
public class TestSeven extends Thread {
private static int x;
public synchronized void doThings() {
int current = x;
current++;
x = current;
}
public void run() {
doThings();
}
}
Run Code Online (Sandbox Code Playgroud)
哪个论述是对的?
A.编译失败.
B.在运行时抛出异常.
C.同步run()方法会使类成为线程安全的.
D.变量"x"中的数据受到保护,不会出现并发访问问题.
E.将doThings()方法声明为static将使类成为线程安全的.
F.在同步(new Object()){}块中包装doThings()中的语句将使该类成为线程安全的.
是不是足以将doThings()标记为已同步以使该类具有线程安全性?我看到正确答案是D但这个问题的模型答案是E,但我不明白为什么?
Thi*_*ilo 19
E.将doThings()方法声明为static将使类成为线程安全的.
这是一个棘手的答案.该方法已经同步,但在实例上,而状态是在静态字段中,即在类上.使它static synchronized确实是正确的答案,因为它在类上同步,而不是在(无意义的)实例上同步.
D.变量"x"中的数据受到保护,不会出现并发访问问题.
private static int x;
Run Code Online (Sandbox Code Playgroud)
这是一个静态变量.它由类的所有实例共享,因此在单个实例上进行同步是没有用的,就像F没有帮助的方式一样,它在完全丢弃的虚拟对象上同步.
Dao*_*Wen 12
根据语言规范:
同步方法在执行之前获取监视器(第17.1节).
对于类(静态)方法,使用与方法类的Class对象关联的监视器.
对于实例方法,使用与此关联的监视器(调用该方法的对象).
这意味着在您提供的代码中,synchronized关键字会导致方法this在执行方法体之前获取锁定.然而,由于x是static不保证更新x将是原子.(该类的另一个实例可以进入同步区域并同时进行更新,因为它们具有不同的this值,因此具有不同的锁定.)
但是,声明doStuffstatic将使对方法的所有调用都获得相同的锁(对象上的那个Class),从而确保方法体中的互斥.
规范确实说明:
class A {
static synchronized void doSomething() {
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
与字面意思完全相同
class A {
static void doSomething() {
synchronized(A.class) {
// ...
}
}
}
Run Code Online (Sandbox Code Playgroud)
同理:
class B {
synchronized void doSomething() {
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
与字面意思完全相同
class B {
void doSomething() {
synchronized (this) {
// ...
}
}
}
Run Code Online (Sandbox Code Playgroud)
通过同步doThings()方法,您将保持特定TestSeven对象的锁定.但是,类的静态变量不属于对象本身的特定实例.它们属于Class对象TestSeven.class.所以,要么你可以去找一个
synchronized (TestSeven.class){
int current = x;
current++;
x = current;
}
Run Code Online (Sandbox Code Playgroud)
在你的doThings()方法中,它正在一个实例锁中获取类锁,这是一个过度的东西.因此,您可以将该方法标记为静态,以便最终单独获取Class对象的锁定.
| 归档时间: |
|
| 查看次数: |
22447 次 |
| 最近记录: |