如果一个同步的方法调用另一个非同步的方法,这个非同步的方法上有锁吗

3zwtqj6y  于 2021-07-06  发布在  Java
关注(0)|答案(4)|浏览(434)

在java中,如果一个同步方法包含对非同步方法的调用,那么另一个方法能否同时访问该非同步方法?基本上我要问的是synchronized方法中的所有东西都有一个锁(包括对其他synchronized方法的调用)?

nle07wnf

nle07wnf1#

如果线程a调用了同步方法m1,而同步方法m1又调用了非同步方法m2,那么线程b仍然可以在不阻塞的情况下调用m2。
synchronized方法获取并释放调用它的对象上的内在锁。这就是它可能阻塞的原因。unsynchronized方法不会尝试获取任何锁(除非在代码中显式完成)。
因此,如果您还需要确保m2的互斥性,那么应该使其同步,而不管其调用者(如m1)是否同步。

rqqzpn5f

rqqzpn5f2#

锁属于线程,而不是方法(或者更准确地说,是它的堆栈帧)。碰巧的是,如果您有一个同步的方法,那么可以保证线程在方法体启动之前拥有锁,然后释放它。
另一个线程仍然可以调用第二个非同步方法。任何线程都可以随时调用未同步的方法。

esyap4oy

esyap4oy3#

锁不属于线程。锁实际上属于对象(或类级别锁中的类),线程在同步上下文中获取对象(或类级别锁中的类)上的锁。现在,java中没有锁传播,正如上面讨论的那样。下面是一个小演示:

public class TestThread {

    /**
     * @param args
     * @throws InterruptedException 
     */
    public static void main(String[] args) throws InterruptedException {
        // TODO Auto-generated method stub
        ThreadCreator1 threadCreator1 = new ThreadCreator1();
        ThreadCreator2 threadCreator2 = new ThreadCreator2();

        Thread t1 = new Thread(threadCreator1,"Thread 1");
        Thread t3 = new Thread(threadCreator1,"Thread 3");
        Thread t2 = new Thread(threadCreator2,"Thread 2");

        t1.start();
        Thread.sleep(2000);
        t3.start();

    }
}
public class ThreadCreator1 implements Runnable {

    private static final Task task= new Task();
    private static final Task2 task2= new Task2();

    @Override

    public void run() {

        try {

            if(Thread.currentThread().getName().equals("Thread 1"))
                task.startTask2(task2);
            if(Thread.currentThread().getName().equals("Thread 3"))
                task2.startTask();

        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        // TODO Auto-generated method stub

        /**/

        }
    }
public class Task {

    public static final Task task = new Task();
    public static List<String> dataList = new ArrayList<String>();
    ReentrantLock lock =  new ReentrantLock();

    public  void startTask2(Task2 task2) throws InterruptedException
    {

        try{

            lock.lock();
            //new Task2().startTask();
            task2.startTask();
        }
        catch(Exception e)
        {

        }
        finally{
            lock.unlock();
        }
    }

}
public class Task2 {

    ReentrantLock lock = new ReentrantLock();
    public  void startTask() throws InterruptedException
    {

        try{
            //lock.lock();
            for(int i =0 ;i< 10;i++)
        {
            System.out.println("***Printing i:"+i+" for:"+Thread.currentThread().getName());
            Thread.sleep(1000);
        }
        }
        catch(Exception e)
        {

        }
        /*finally
        {
            lock.unlock();
        }*/
    }

}

只是我在这里用了重入锁。如果运行了上述代码,那么线程1和线程3之间将进行交错,但是如果task2类的锁部分没有注解,那么将不进行交错,并且首先获取锁的线程将首先完全完成,然后它将释放锁,然后另一个线程可以继续。

eqzww0vc

eqzww0vc4#

如果一个同步方法调用另一个非同步方法,那么该非同步方法上是否有锁
是和否。
如果你身处困境 synchronized 方法,然后由其他线程调用同一对象示例的其他方法 synchronized 锁上了。但是,其他线程对非同步方法的调用不会被锁定—任何人都可以同时调用它们。

public synchronized void someSynchronizedMethod() {
    ...
    someNonSynchronizedMethod();
    ...
}

// anyone can call this method even if the someSynchronizedMethod() method has
// been called and the lock has been locked
public void someNonSynchronizedMethod() {
   ...
}

另外,如果你打电话 someSynchronizedMethod() 但恰好在 someNonSynchronizedMethod() 方法,你仍然持有锁。当您输入同步方法(或块)时,将启用锁定,当您退出该方法时,将禁用锁定。您可以调用各种其他未同步的方法,但它们仍将被锁定。
但你的问题有两个不同的问题:
在java中,如果一个同步方法包含对非同步方法的调用,那么另一个方法能否同时访问该非同步方法?
对。其他方法可以访问非同步方法。
基本上我要问的是synchronized方法中的所有东西都有一个锁(包括对其他synchronized方法的调用)?
嗯,是的。对同步方法的其他调用被锁定。但是不同步的方法不会被锁定。
另外,请记住,如果方法 static 那么锁就在门上了 Class 中的对象 ClassLoader .

// this locks on the Class object in the ClassLoader
public static synchronized void someStaticMethod() {

如果方法是示例方法,那么锁就在类的示例上。

// this locks on the instance object that contains the method
public synchronized void someInstanceMethod() {

在这两种情况下有两种不同的锁。
最后,当你处理 synchronized 示例方法,类的每个示例都被锁定。这意味着两个线程可以在同一个线程中 synchronized 方法同时使用不同的示例。但是如果有两个线程尝试在 synchronized 方法,其中一个将阻塞,直到另一个退出该方法。

相关问题