Java null check

末鹿安然 提交于 2019-12-12 12:09:19

问题


I have one thread1:

if(object != null){
   object.play();
}

and another thread2 that can write null into object reference at any time.

I will run these threads at same time. I know thread2 can rewrite object reference after the null check and that will throw NullPointerException. Is it possible for thread2 to rewrite object reference after NullPointerException check?


回答1:


Is it possible to for thread2 to rewrite object reference after NullPointerException check ?

Absolutely - it could change the value of object while the play() method is executing, if that's what you mean. That wouldn't cause an error in itself.

Note that without synchronization or other memory barriers, thread2 could change the value of object without thread1 noticing for an indeterminate period of time.

It's hard to say what you ought to do, without any other knowledge of the bigger aim of the code.




回答2:


Simple synchronized example:

/**
To maintain thread safety, only access this through getter and setter
or other synchronized method
**/
private ObjectType object;

public synchronized void setObject(ObjectType object) {
  this.object = object;
}

public synchronized ObjectType getObject() {
  return object;
}

public void doPlay() {
  final ObjectType obj = getObject();
  //here, thread 2 can change "object", but it's not going to affect this thread
  //as we already safely got our reference to "object" in "obj".
  if(obj != null){ 
   obj.play(); 
  }
}

public synchronized void alterativeDoPlay() {
  //the difference here is that another thread won't be able to change "object"
  //until the object's play() method has completed.
  //depending on the code in play, this has potential for deadlocks, where as
  //the other `doPlay` has zero deadlock potential.
  if(object != null){
   object.play(); 
  }
}



回答3:


If object is an instance variable or a static variable that can be changed from multiple threads, its value can change between the time you test it in the if statement and the time when you call its instance method.

You can modify the code to avoid this problem by copying the object into a local variable, like this:

Playable objectCopy = object;
if(objectCopy != null) {
    objectCopy.play();
}

Since objectCopy is a local variable, its value cannot change between the test and the call of play. Of course the state of the playable object itself can change, but that is not something that can be fixed by null checking.




回答4:


You can use CountDownLatch here. Where Thread1 will wait to count down by Thread2 and you can perform the task in thread2 and stop count down.

Code snippet -

CountDownLatch latch = new CountDownLatch(1);
new Thread1(latch).start();
new Thread2(latch).start();
public class Thread1 extends Thread {
  private final CountDownLatch startLatch;

  public Thread1(CountDownLatch startLatch) {
    this.startLatch = startLatch;
  }
  public void run() {
    try {
      startLatch.await();
      // ... perform task
    } catch (InterruptedException iex) {}
  }
}

public class Thread1 extends Thread {
  private final CountDownLatch stopLatch;

  public Thread1(CountDownLatch stopLatch) {
    this.stopLatch = stopLatch;
  }
  public void run() {
    try {
      // perform task
    } finally {
      stopLatch.countDown();
    }
  }
}



回答5:


According to Brian's Law :

When we write a variable, which next has to be read by another thread, or when we are reading a variable which has lately been written by another thread, then use synchronization. Synchronize the atomic statements or getter/setters which has access to the crucial state of data with the same monitor lock.

- Use synchronization.

- You can use CountDownLatch from java.util.concurrent




回答6:


You will need to use some form of synchronisation primitive to solve this problem. See "Syncrhonised Statements" here. In your case you will need to wrap the whole if block and any places in any threads that use or update object2.




回答7:


As my professor said: "Concurrency is a pretty unstable guy. We never know what to expect of him." Comming to your question:

Is it possible for thread2 to rewrite object reference after NullPointerException check?

Yes

Thread2 can access the object many times during 1 occurrence of thread1. Or the other way around. There may be many occurrences of thread1, while thread2 accesses the object.

If you use simple

System.out.println();

in many places in your code, you may notice the output in the console to be displayed AFTER the NullPointerException error(if it wasn't caught).



来源:https://stackoverflow.com/questions/12781828/java-null-check

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!