开发者

Can two threads run two different methods at the same point of time?

class A {
    private synchronized f() {
        ...
        ...
    }

    private void g() {
 开发者_如何学Python       ...
        ...
    }
}

If thread T1 is running f() which is synchronized, can thread t2 run g() which is not synchronized at the same point of time, while T1 is still running f()?


Not on the same instance of A. The instance itself is the lock so two execute the two methods at the same time with two threads you would need two instances of A.


Yes. Both methods can execute at the same time on the same instance.

Only f() is synchronized. A thread must acquire the monitor for this.f() to execute f() and only one monitor exists per instance.

g() is not synchronized, no monitor locking is required to run the method, so any thread can execute g() at any time.

"A synchronized method acquires a monitor (§17.1) before it executes."

http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.4.3.6


No. One call will block until the other completes. The reason for this is that the synchronized keyword on a method expands to synchronize on the current instance of the object. To be more specific, consider this code:

private void synchronized f() {
  ...
}

The above code is identical in functionality to the following code:

private void f() {
  synchronized (this) {
    ...
  }
}

So if you want two methods in an object to be synchronized only to each other, you should create two lock objects. Each method should wrap all of its code inside a synchronized (object) block, one object for each method.


Yes, if T1 and T2 are executing f and g respectively on different instances of A.

If both threads are executing a method on the same instance of A, only one will be able to execute a method at a time. If T1 runs first, it will acquire the lock on the instance of A, and execute method f. Thread T2 will be unable to execute method g until after T1 has finished executing f. Or the opposite could happen: T2 could run g first, and T1 won't be able to run f until after T2 has finished.


In general, two threads can run two methods at the same point in time; however, in your example only one thread might be running f() or g() at any given moment.

Using the synchronized keyword changes thread interactions. Every java object has a lock, an item that only one thread can hold at any given time. Synchronized is a command that directs the threads to acquire the lock before execution of a method and release it afterward. The lock is held during the entire execution of the method.

In your example, only one thread will be executing f() or g() at any given time because the "other" thread will be waiting its turn to grab the lock.

When you have two objects of the same class, you have two locks. That means you could get two threads to run f() and g() simultaneously with the synchronized keywords intact, as the threads will be grabbing locks on different objects. You just can't get threads to execute simultaneously on the same object without removing the synchronized keyword.


The correct answer to this is reassembler's answer.

Run this and you'll see. You can also test using Thread.sleep() instead of an infinite loop by uncommenting/commenting the according sections of the sample.

I apologize if the code doesnt follow best practices, my java is pretty rusty.

package threadtest;

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;


public class ThreadTest {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws IOException {
        TestClass tc = new TestClass();

        // invokes not sync method
        FirstThreadRunnable ftr = new FirstThreadRunnable(tc);
        Thread t1 = new Thread(ftr);

        // invokes the sync method
        SecondThreadRunnable str = new SecondThreadRunnable(tc);
        Thread t2 = new Thread(str);

        t2.start();
        t1.start();


        System.in.read();
    }

    public static class TestClass {

        private int callCount = 0;

        public void notSynchronizedMethod() {
            System.out.println("notSynchronizedMethod says hello!" + " [" + callCount++ +"] from thread: " + Thread.currentThread().getId());
        }

        public synchronized void synchronizedMethod() throws InterruptedException {
            // Test with the sleep
            //System.out.println("entering sync method and pausing from thread: " + Thread.currentThread().getId());
            //Thread.sleep(5000); // hold the monitor for 5sec
            //System.out.println("exiting sync method"  + " [" + callCount++ +"] from thread: " + Thread.currentThread().getId());

            // Test with spinning
            System.out.println("MAKE IT SPIN! from thread: " + Thread.currentThread().getId());
            boolean spin = true;
            while(spin){

            }
            System.out.println("IT STOPPED SPINNING! from thread: " + Thread.currentThread().getId());
        }
    }

    // invokes the not sync method
    public static class FirstThreadRunnable implements Runnable {
        TestClass tester = null;
        public FirstThreadRunnable(TestClass tester){
            this.tester = tester;
        }


        @Override
        public void run() {
            for(int i = 0; i < 500; i++){
                tester.notSynchronizedMethod();
                try {
                    Thread.sleep(50);
                } catch (InterruptedException ex) {
                    Logger.getLogger(ThreadTest.class.getName()).log(Level.SEVERE, null, ex);
                }
            }

        }
    }

    // invokes the sync method
    public static class SecondThreadRunnable implements Runnable {

        TestClass tester = null;
        public SecondThreadRunnable(TestClass tester){
            this.tester = tester;
        }

        @Override
        public void run() {
            try {
                // Test with Sleep()
                //for(int i = 0; i < 5; i++){
                //  tester.synchronizedMethod();
                //}

                // Test with the spinning
                tester.synchronizedMethod();

            } catch (InterruptedException ex) {
                Logger.getLogger(ThreadTest.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
}


for the interest of technicality and pedanticality, yes, both methods could be entered at the same time. one is blocked on synchronized (this), non the less, the method is entered and running, it's first statement is being executed, and the first byte code instruction is carried out.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜