简体   繁体   English

为什么子线程中的同步方法持有主线程的锁

[英]why synchronized method in the sub thread hold the lock of main thread

I have a synchronized method. 我有一个同步方法。 then I will start a Thread with long time operation, the sub-thread also have a synchronized method, But the synchronized method in sub thread will hold the lock of the synchronized method which will cause anr in my appliction. 然后我将启动一个长时间运行的线程,子线程也有一个同步方法,但是子线程中的同步方法将持有该同步方法的锁,这会在我的应用中引起麻烦。

My code is: 我的代码是:

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();
        }
    }
}

It is standard behavior of synchronized methods. 它是同步方法的标准行为。

Look at http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html 查看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. 当一个线程正在执行对象的同步方法时,所有其他调用同一对象块的同步方法的线程(挂起执行),直到第一个线程对该对象完成。

So code 所以代码

public synchronized void method() { 
} 

is equivalent to 相当于

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

For your purposes you should use different lock-objects for connectToServer and restart methods 为了您的目的,您应该为connectToServerrestart方法使用不同的锁定对象

UPD. UPD。 Sorry, I missed, that your methods are static. 对不起,我想念您的方法是静态的。 In this case specification 8.4.3.6 在这种情况下, 规范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. 对于类(静态)方法,使用与该方法的类的Class对象关联的监视器。

So you can not run two synchronized methods of a class simultaneously, even if they are static 因此,即使它们是静态的,也不能同时运行一个类的两个同步方法

Blocking the main UI thread for 5 secods or more causes the ANR. 将主UI线程阻塞5秒或更长时间会导致ANR。

from Anr Message with synchronized method Anr Message使用同步方法

Maybe that's happening because of: 可能是因为:

Thread.sleep(20000); 

Avoid to lock the main UI thread. 避免锁定主UI线程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM