1

我有简单的代码:

public class testing {
    private static Object objToSync = new Object();

    public static void main(String[] args) {
        String obj1 = null;
        synchronized(objToSync){
            System.out.println("something one");                    
            doSomething();
            System.out.println("something three ");         
        }

        doSomething();      
    }

    private static void doSomething() {
        synchronized(objToSync){
            System.out.println("something two");
        }       
    }

我已经阅读了几件事,但仍然对此感到困惑。为什么调用 main 中的 doSomething ?难道不应该等到同步对象解锁吗?对不起,如果我听起来很愚蠢,我只是很困惑。

4

4 回答 4

11

难道不应该等到同步对象解锁吗?

锁由thread持有,因此您在其上同步两次(在第一次调用 in 的情况下doSomething)这一main事实并不重要,它在同一个线程上。如果另一个线程随后尝试进入synchronized上的块objToSync,则该其他线程将等待直到该线程释放其所有锁。

您的代码将执行此操作:

  1. 进入main
  2. objToSync获取对象上当前线程的锁
  3. 输出“某物”
  4. 称呼doSomething
  5. 为当前线程获取第二个锁objToSync
  6. 输出“东西二”
  7. 释放当前线程的第二个锁objToSync
  8. 从返回doSomething
  9. 输出“三点”
  10. 释放当前线程的第一个锁objToSync
  11. 称呼doSomething
  12. 获取一个新的锁(对于同一个线程)objToSync
  13. 输出“东西二”
  14. 释放那个锁
  15. 从返回doSomething
  16. 从返回main

这是一个使用两个线程的示例:

public class SyncExample {

    private static Object objToSync = new Object();

    public static final void main(String[] args) {
        Thread second;

        System.out.println("Main thread acquiring lock");
        synchronized (objToSync) {
            System.out.println("Main thread has lock, spawning second thread");
            second = new Thread(new MyRunnable());
            second.start();
            System.out.println("Main thread has started second thread, sleeping a moment");
            try {
                Thread.currentThread().sleep(250);
            }
            catch (Exception e) {
            }
            System.out.println("Main thread releasing lock");
        }
        System.out.println("Main thread sleeping again");
        try {
            Thread.currentThread().sleep(250);
        }
        catch (Exception e) {
        }
        System.out.println("Main thread waiting for second thread to complete");
        try {
            second.join();
        }
        catch (Exception e) {
        }
        System.out.println("Main thread exiting");
    }

    static class MyRunnable implements Runnable {

        public void run() {
            System.out.println("Second thread running, acquiring lock");
            synchronized (objToSync) {
                System.out.println("Second thread has lock, sleeping a moment");
                try {
                    Thread.currentThread().sleep(250);
                }
                catch (Exception e) {
                }
                System.out.println("Second thread releasing lock");
            }
            System.out.println("Second thread is done");
        }
    }
}

输出:

主线程获取锁
主线程有锁,产生第二个线程
主线程已经启动了第二个线程,睡了一会儿
第二个线程运行,获取锁
主线程释放锁
主线程再次休眠
第二个线程有锁,睡一会儿
主线程等待第二个线程完成
第二个线程释放锁
第二个线程完成
主线程退出
于 2012-07-03T16:59:55.873 回答
5

锁是reentrant如此,如果某些线程拥有锁,它可以基于该锁进入其他同步块。在您的情况下,您只有一个线程(主线程),而他正在做这样的事情

synchronized(objToSync){
    System.out.println("something one");                    
    synchronized(objToSync){
        System.out.println("something two");
    }
    System.out.println("something three");
}
于 2012-07-03T17:05:57.100 回答
2

锁是同一线程的可重入。这意味着已获得对象锁定的线程可以访问对象的 this 和任何其他同步方法(或原子语句,如您的示例中的此处)。一旦获得锁,该线程将不需要再次获得锁。

于 2012-07-03T17:10:45.280 回答
1

那是因为你的程序只有 1 个线程——主线程。

于 2012-07-03T17:00:22.393 回答