【问题标题】:Java Thread Synchronization Concept Static Function [duplicate]Java线程同步概念静态函数[重复]
【发布时间】:2014-06-30 00:49:37
【问题描述】:

最近我的朋友在一次采访中被问到这个问题。

问题:我们有 A 类,有 2 个方法 X1 和 X2。 X1 是静态同步的,X2 是同步的。

class A {
    public static synchronized X1() {
    }
    public synchronized X2() {
    }
}

现在我们知道静态同步获得了 CLASS 上的锁,而同步获得了调用对象上的锁。

面试官问“锁定CLASS是什么意思?”。锁定总是在对象上完成。那么在静态同步的情况下实际会发生什么。它锁定了 WHICH OBJECT?

有人能帮我澄清一下这个概念吗,因为这里有点混乱。

【问题讨论】:

  • 不要说“静态同步”。 “静态”比仅指定在调用方法时锁定哪个互斥锁更重要。
  • 我应该说的是:你让它听起来像“静态”是为了改变“同步”的含义。它确实做到了,但这只是其更广泛含义的副作用; “静态”的真正含义是调用方法时不引用类的任何实例(即没有 this 引用)。由于没有this,那么显然该方法无法在this上同步。它在类对象上同步,因为这是下一个最明显的选择。

标签: java multithreading synchronized


【解决方案1】:

根据Oracle concurrency tutorial

你可能想知道当一个静态同步方法是 调用,因为静态方法与类相关联,而不是 目的。在这种情况下,线程为 与类关联的类对象。从而访问类的静态 字段由不同于任何锁的锁控制 类的实例。

【讨论】:

  • 换句话说,synchronized(ClassName.class) { ... }
  • 什么是类对象?
  • @learner 这完全是另一个问题,您只需稍加努力即可找到答案。搜索网络或 stackoverflow。
  • @Sotirious 我对“与类关联的类对象的内在锁”感到困惑。这是否意味着该特定类的超类对象锁定?
  • @learner,Class类的一个实例:docs.oracle.com/javase/7/docs/api/java/lang/Class.html
【解决方案2】:

正如SO answer 准确指出的那样

there is no link between synchronized static methods and sync'ed non static methods in 
this context

为了证明这一点。

public class SimpleClassTest {

静态同步方式

public static synchronized void X1() {
        System.out.println("Before X1 Exec.. From"+Thread.currentThread().getName());
        try {
            Thread.currentThread().sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("After X1 Exec.. From"+Thread.currentThread().getName());
    }

非静态同步方法

public synchronized void X2() {
        System.out.println(" X2 Exec.. From"+Thread.currentThread().getName());
    }

第一种方法只是休眠一段时间然后醒来。 第二种方法同步但不是静态的。

现在尝试创建两个线程并同时调用这个方法(大约)

public static void main(String args[]){
        final SimpleClassTest instance = new SimpleClassTest();

静态的第一个线程

    Thread t1 = new Thread(new Runnable() {

        @Override
        public void run() {
            SimpleClassTest.X1();
        }
    },"Thread1");

非静态的第二个线程

    Thread t2 = new Thread(new Runnable() {

        @Override
        public void run() {
            instance.X2();
        }
    },"Thread2");

现在启动两个线程

    t1.start();
    t2.start();

结果

Before X1 Exec.. FromThread1
 X2 Exec.. FromThread2
After X1 Exec.. FromThread1

从结果来看,两个线程运行时没有相互锁定。因为如果第一个线程锁定了第二个线程锁定的同一个对象,那么线程 2 将等待第一个线程完成。

因此,我们确信两者都是并行运行的。

第一个线程锁定了 SimpleClasstest.class,因为它是与实例无关的静态方法。

第二个线程锁定实例,因为它是非静态的。

希望可以解决

【讨论】:

  • 反对选民,请发表评论。这样我可以找到错误,如果有的话
  • 问题是:“哪个对象的内在锁是由调用类的同步静态方法的线程获取的?”。我不明白为什么你的几十行代码回答了这个问题。 (答案应该是这样的:“线程获取与类关联的类对象的锁。所以在你的情况下,它相当于:同步(A.class){...}”)。
  • 已成为经典...我没有投反对票,但我想这是因为您回答了错误的问题。不是“Are the locks on the same Object?”,而是“静态版本锁定了什么?”,您只用一行简单地触及了它,没有任何解释。
  • @isnot2bad 和 Ordous 感谢您的评论。我认为另一个答案提供了完美的链接来澄清这一点。想提供一些关于会发生什么的例子。现在我明白了原因。我应该只讨论锁定“SimpleClasstest.class”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-25
  • 2011-09-20
  • 1970-01-01
  • 1970-01-01
  • 2011-01-20
  • 1970-01-01
相关资源
最近更新 更多