Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent non thread-safe method to be used in multithreaded context

Is there a way to throw an exception when a user tries to use a non thread-safe method of a class in a multithreaded context? I guess the issue is mostly to detect that multiple threads are trying to use the method. Or, is there a "not_synchronous" keyword/tag I could use on the function declaration?

like image 808
Frank Avatar asked Jul 31 '12 16:07

Frank


People also ask

What is non thread-safe?

Non-thread-safe: It does not check the safety of the threads which makes it faster to run but at the same time, it becomes more unstable and crashes very frequently. It refers to a single thread only builds.

How can we ensure that instance of this class can be safely used by multiple threads?

Using Volatile keyword A volatile keyword is a field modifier that ensures that the object can be used by multiple threads at the same time without having any problem. volatile is one good way of ensuring that the Java program is thread-safe.

Is scanner is safe for multithreaded use?

A Scanner breaks its input into tokens using a delimiter pattern, which by default matches whitespace. A scanning operation may block waiting for input. A Scanner is not safe for multithreaded use without external synchronization.


3 Answers

You could check whether the method is already in use before allowing a thread to run it - but that is not very different from using a lock (note: my example is not reentrant):

private static final AtomicBoolean used = new AtomicBoolean();

public static void unsafe() throws InterruptedException {
    if(!used.compareAndSet(false, true)) {
        throw new IllegalStateException();
    }
    //do you stuff
    used.set(false);
}
like image 95
assylias Avatar answered Oct 20 '22 07:10

assylias


There is no easy way to do this, no. If you are detecting that multiple threads are using a method, then chances are you will have to be using thread-safe collections and the like. If you are doing all that then you might as well have to make the method itself thread-safe.

like image 43
Gray Avatar answered Oct 20 '22 05:10

Gray


To expand on Gray's answer: suppose you wanted to do this (detect when a method is being used by multiple threads). A naive (and incorrect) implementation of this might look like:

volatile boolean methodBeingUsed = false;
public void doSomething() {
  if (methodBeingUsed) throw new IllegalStateException("You can't do that!");
  try {
    methodBeingUsed = true;
    // do something...
  } finally {
    methodBeingUsed = false;
  }
}

Well, OK... but two threads could both get past the first if (methodBeingUsed) check and enter the critical section at the same time. So now maybe we try adding a lock to protect the methodBeingUsed flag:

Lock methodLock = new ReentrantLock();
volatile boolean methodBeingUsed = false;
public void doSomething() {
  try {
    lock.lock();
    if (methodBeingUsed) throw new IllegalStateException("You can't do that!");
    methodBeingUsed = true;
  } finally {
    lock.unlock();
  }

  try {
    // do something...
  } finally {
    try {
      lock.lock();
      methodBeingUsed = false;
    } finally {
      lock.unlock();
    }
  }
}

Of course, this assumes that doSomething() can't recursively call itself. If it can, then you also have to keep track of the calling thread. Add in some more checks to account for other conditions that I'm not thinking of right now, and it's easy to see that the effort spent synchronizing the logic to detect the method being used by multiple threads would be better spent just making the method thread-safe to begin with.

like image 41
Alex Avatar answered Oct 20 '22 05:10

Alex