有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!


共 (6) 个答案

  1. # 1 楼答案

    不在A的同一个实例上。实例本身就是锁,所以两个线程同时执行这两个方法,你需要A的两个实例

  2. # 2 楼答案

    不。一个呼叫将被阻止,直到另一个呼叫完成。原因是方法上的synchronized关键字会扩展为在对象的当前实例上同步。更具体地,考虑这个代码:

    private void synchronized f() {
      ...
    }
    

    上述代码在功能上与以下代码相同:

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

    因此,如果希望一个对象中的两个方法只相互同步,那么应该创建两个锁对象。每个方法都应该将其所有代码封装在一个同步(对象)块中,每个方法对应一个对象

  3. # 3 楼答案

    是的,如果T1和T2分别在A的不同实例上执行fg

    如果两个线程都在同一个实例上执行一个方法,那么一次只能有一个线程执行一个方法。如果T1首先运行,它将获取A实例上的锁,并执行方法f。线程T2将无法执行方法g,直到T1完成执行f。或者相反的情况可能发生:T2可以先运行^{,而T1在T2完成之前无法运行^{

  4. # 4 楼答案

    正确的答案是重组者的答案

    运行这个,你会看到的。您还可以使用线程进行测试。sleep()而不是无限循环,方法是取消对示例相应部分的注释/注释

    如果代码没有遵循最佳实践,我深表歉意,我的java已经生锈了

    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);
                }
            }
        }
    }
    
  5. # 5 楼答案

    对。这两种方法可以在同一实例上同时执行

    只有f()是同步的。线程必须获取this.f()的监视器才能执行f(),并且每个实例只存在一个监视器

    g()不同步,运行该方法不需要监视器锁定,因此任何线程都可以随时执行g()

    “同步方法在执行之前获取监视器(§17.1)。”

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

  6. # 6 楼答案

    通常,两个线程可以在同一时间点运行两个方法;然而,在您的示例中,在任何给定时刻,只有一个线程可能正在运行f()g()

    使用synchronized关键字可以更改线程交互。每个java对象都有一个锁,一个在任何给定时间只有一个线程可以持有的项Synchronized是一个命令,它指示线程在执行方法之前获取锁,然后释放它。锁在方法的整个执行过程中保持

    在您的示例中,在任何给定时间,只有一个线程将执行f()g(),因为“另一个”线程将等待轮到它来获取锁

    如果有两个同一类的对象,则有两个锁。这意味着您可以让两个线程同时运行f()g(),同时保持synchronized关键字不变,因为线程将在不同的对象上获取锁。如果不删除synchronized关键字,就无法让线程在同一个对象上同时执行