关于同步功能

时间:2017-02-08 11:14:29

标签: java

我接受了采访,我被问到一个有两个函数m1()和m2()的类。 m1()是同步的,而m2()不是,并且两个线程t1和t2正在尝试访问此对象。现在如果t1正在访问m1()函数,那么t2可以同时访问m2()方法吗?

我说应该允许它访问它,因为m2()方法没有锁定,但是访问者坚持认为,因为锁定在同一个对象上,所以不允许访问m2()函数为t2线程。

为此,我写了一个检查程序,发现无论我说的是对的。请查看带有输出的程序。

class myExperiment2 implements Runnable{
    myThreadEx m;

    myExperiment2(myThreadEx m){
        this.m = m;
    }

    @Override
    public void run() {
        try {
            m.m2();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class myExperiment1 implements Runnable{
    myThreadEx m;

    myExperiment1(myThreadEx m){
        this.m = m;
    }

    @Override
    public void run() {
        try {
            m.m1();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

class myThreadEx{

    synchronized void m1() throws InterruptedException {
        System.out.println("1 am in m1....1");
        Thread.sleep(10000);
        System.out.println("I am in m1()");
        Thread.sleep(10000);
        System.out.println("1 am in m1....2");
    }

    void m2() throws InterruptedException{
        System.out.println("1 am in m2....1");
        Thread.sleep(5000);
        System.out.println("i am in m2()");
        Thread.sleep(5000);
        System.out.println("1 am in m2....2");
    }
}

public class ThreadEx {

    public static void main(String args[]){
        myThreadEx m = new myThreadEx();

        Thread t1 = new Thread(new myExperiment1(m));
        Thread t2 = new Thread(new myExperiment2(m));

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

输出

  

上午1点在m1 .... 1   凌晨1点在m2 .... 1
  我在m2()
  凌晨1点在m2 .... 2
  我在m1()
  凌晨1点在m1 .... 2

如果我遗失某些东西,或者有可能出现我可能出错的情况,无论采访是什么,有人可以建议我,是吗?

3 个答案:

答案 0 :(得分:3)

除非我误解了这个问题,否则你没有准确地联系到这个问题,面试官就错了。

当然,给定the semantics of synchronized methods

synchronized void foo() { ... }

相同
void foo() { synchronized (this) { ... } }

(至少对于一个实例方法)

然后其他线程总是可以同时“访问”该方法(例如,多个线程在其堆栈跟踪中具有该方法);他们马上被阻止了。

答案 1 :(得分:1)

我会说面试官错了。如果m1m2同步,他就会是对的。在你的问题的情况下,没有与m2相关联的锁,因此没有什么能阻止其他线程执行它。

答案 2 :(得分:0)

面试官错了,除非他的意思如下,

您可以采用两种类型锁定策略

  1. 对象的内在锁(this,如您的情况或HashTable)
  2. 下面定义的私人锁定
  3. 私人锁,

    public class PrivateLock {
       private final Object myLock = new Object();
       @GuardedBy("myLock") Widget widget;
    
       void someMethod() {
          synchronized(myLock) {
               // Access or modify the state of widget
          }
       }
    }
    

    所以,如果某人正在做以下操作会导致m2无法调用,

    //myThreadEx also shared by another class which does myThreadEx.m1
    synchronized(myThreadEx) {
        myThreadEx.m2(); 
    }