If a synchronized method calls another non-synchro

2019-01-08 14:52发布

In Java, if a synchronized method contains a call to a non-synchronized, can another method still access the non-synchronized method at the same time? Basically what I'm asking is everything in the synchronized method have a lock on it (including calls to other synchronized methods)? Thanks so much

4条回答
女痞
2楼-- · 2019-01-08 15:37

If thread A calls synchronized method M1 which in turn calls unsynchronized method M2, then thread B can still call M2 without blocking.

Synchronized method acquires and releases intrinsic lock on the object on which it is called. This is why it may block. Unsynchronized method doesn't attempt to acquire any lock (unless it is done explicitly in the code).

Thus, if you need to ensure mutual exclusion for M2 as well, you should make it synchronized regardless of whether its callers (like M1) are synchronized or not.

查看更多
The star\"
3楼-- · 2019-01-08 15:45

The lock belongs to the thread, not to the method (or more precisely, its stack frame). It just so happens that if you have a synchronized method, you're guaranteed that the thread will own the lock before the body of the method start, and will release it afterwards.

Another thread can still invoke the second, non-synchronized method. An unsynchronized method can be called by any thread at any time.

查看更多
淡お忘
4楼-- · 2019-01-08 15:46

The lock doesn't belong to the thread. The lock actually belongs to the object(or Class in case of Class level lock), and a thread acquires lock on the Object(or Class in case of Class level lock) within a synchronized context. Now, there is no lock propagation in java as it is discussed above. Here is a small demo:

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

}

Just I have used Reentrant lock here. If the above code is run, then there will be interleaving between thread 1 and thread 3, but if the lock portion of Task2 class is uncommented, then there will be no interleaving and the thread which acquire the lock first will complete fully first, then it will release the lock and then the other thread can carry on.

查看更多
相关推荐>>
5楼-- · 2019-01-08 15:50

If a synchronized method calls another non-synchronized method, is there a lock on the non-synchronized method

Yes and no.

If you are in a synchronized method, then calls to other methods that are also synchronized by other threads are locked. However calls to non-synchronized methods by other threads are not locked -- anyone can call them at the same time.

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() {
   ...
}

Also, if you call someSynchronizedMethod() but happen to be within the someNonSynchronizedMethod() method, you still hold the lock. The lock is enabled when you enter a synchronized block and is disabled when you exit that method. You can call all sorts of other unsynchronized methods and they will still be locked.

But you are asking two different things in your question:

In Java, if a synchronized method contains a call to a non-synchronized, can another method still access the non-synchronized method at the same time?

Yes. Other methods can access non-synchronized methods.

Basically what I'm asking is everything in the synchronized method have a lock on it (including calls to other synchronized methods)?

Uh, yes. Other calls to synchronized methods are locked. But non-synchronized methods are not locked.

Also, remember that if the method is static then the lock is on the Class object in the ClassLoader.

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

If the method is an instance method then the lock is on the instance of the class.

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

There are 2 different locks in those 2 cases.

Lastly, when you are dealing with synchronized instance methods, each instance of the class is what is locked. This means that two threads could be in the same synchronized method at the same time with different instances. But if 2 threads try to operate on synchronized methods on the same instance, one will block until the other one exits the method.

查看更多
登录 后发表回答