java - 为什么子线程中的synchronized方法会持有主线程的锁

标签 java android multithreading

我有一个同步方法。然后我将启动一个长时间运行的线程,子线程也有一个同步方法,但是子线程中的同步方法将持有同步方法的锁,这将导致我的应用程序中出现错误。

我的代码是:

import java.util.Date;

public class ThreadTest {

    static MQTTThread mThread;

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            System.out.println("the  " + i + " -  restart time =  "
                    + new Date());
            restart(i);
        }
    }

    private static synchronized void restart(int i) {
        System.out.println("the " + i + " -  restart excute " + new Date());
        if (null != mThread) {
            if (!mThread.isAlive()) {
                try {
                    System.out
                    .println("Action:restartConnectThread in mThread.runFlag)");

                    mThread = new MQTTThread();
                    mThread.setName("MQTTThread");
                    mThread.start();
                    // mqttExecutor.execute(mThread);
                } catch (Exception e) {
                    System.out.println("!mThread.runFlag");
                }
            } else {
                System.out.println("Action:restartConnectThread - CONNECTING");
            }
        } else {
            try {
                System.out
                .println("Action:restartConnectThread in null thread");
                mThread = new MQTTThread();
                mThread.setName("MQTTThread");
                mThread.start();
            } catch (Exception e) {
                System.out.println("null mThread");
            }
        }
    }

    private static class MQTTThread extends Thread {
        public void run() {

            connectToServer();
            System.out.println("connected");
        }
    }

    public static synchronized void connectToServer() {
        try {
            System.out.println("Thread.sleep " + new Date());
            Thread.sleep(20000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

最佳答案

这是同步方法的标准行为。

看看http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.

所以代码

public synchronized void method() { 
} 

相当于

public void method() { 
    synchronized (this) {
    }
}

出于您的目的,您应该为 connectToServerrestart 方法使用不同的锁定对象

UPD。抱歉,我错过了,您的方法是静态的。在这种情况下specification 8.4.3.6

A synchronized method acquires a monitor before it executes. For a class (static) method, the monitor associated with the Class object for the method's class is used.

所以你不能同时运行一个类的两个同步方法,即使它们是静态的

关于java - 为什么子线程中的synchronized方法会持有主线程的锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24360710/

相关文章:

Java:使用 Scanner 在方法中添加项目

java - 当项目本身用空格分隔时,如何分隔由空格组成的文件中的项目?

java - JComboBox 程序无法加载

如果没有下载,Java android检查是否安装了Acrobat Reader

c# - AutoResetEvent澄清

web-services - 从线程调用远程 SOAP 调用时发生异常

java - Spring Boot 应用程序中日志记录概念的行数

javascript - 单击事件在 iPad/iPhone/Android 上的动态构建元素上不起作用

android - 如何解决 Android 错误类型 3?

java - EDT 更改为 "system"组且 Thread.currentThread().getContextClassLoader() 为 null