I'm doing this little exercise myself trying to understand how should I work with concurrency and threads.
It happens that sometimes I have an object that I can't modify its source code and that is not thread-safe, so I want it to be accessed just by one thread.
In this example that thirdparty object that I can't touch is called Holdeable. What I do is trying to wrap it into a class called Holder that has synchronized methods, and I expect that by doing it only one thread can access that Holdeable object. At sometime I null the reference to the Holdeable object and I want it properly done so when the other thread evaluates mHolder.getHoldeable()==null is true, and avoids entering the code that can cause a NullPointerException.
My last attempt included a synchronized block, which is this:
class Holder {
Holdeable mHoldeable;
public synchronized void setHoldeable(Holdeable holdeable) { mHoldeable = holdeable; }
public synchronized Holdeable getHoldeable() { return mHoldeable; }
}
class Holdeable { // Cannot be modified, that would be to cheat :D
public int someValue;
}
public class MainClass {
private static Holder mHolder;
public static void main(String[] args) {
try {
Holdeable holdeable = new Holdeable();
mHolder = new Holder();
mHolder.setHoldeable(holdeable);
new Thread(new Runnable() {
#Override
public void run() {
try {
while(true) {
synchronized(mHolder) {
if(mHolder.getHoldeable() != null) {
Thread.sleep(23);
System.out.println(mHolder.getHoldeable().someValue);
} else {
System.out.println("No holder!");
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
Thread.sleep(1000);
mHolder.getHoldeable().someValue = 2;
Thread.sleep(1500);
mHolder.getHoldeable().someValue = 3;
Thread.sleep(500);
mHolder.setHoldeable(null);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
This example avoids throwing a NullPointerException, but as you can see, it just takes a lot to execute with so much locking. I'm struggling with this while I read the book "The art of concurrency" to see if I finally get it.
What do you think?
Your code is not thread-safe. You have two levels of locking:
Holder's methods are synchronized;
you synchronize on the Holder instance.
Point 1. doesn't give you enough synchronization because it covers only fetching holdeable and not accessing its properties;
Point 2. doesn't give you any synchronization at all because you are acquiring the lock only in one thread.
I suggest you use only point 2. and apply it consistently.
BTW your program takes so long to execute because it calls Thread.sleep. The performance of locking is way too high for you to be able to notice it without involving tight loops repeating at least hundreds of thousands of times.
public class Holder {
final Holdeable mHoldeable;
Holder(Holdeable holdeable) {
this.mHoldeable = Objects.requireNonNull(holdeable, "Holdeable cannot be null");
}
Holdeable get() {
return mHoldeable;
}
}
Using this construct will make your life so much easier. And as you might have noticed: it as well removes the need to synchronize. And if I ever write a book, that would be in it on page one. ;)
Threading and synchronization is done almost 100% on architectural level, adding some synchronized blocks is just a backup/quick & dirty solution.
Related
I have two synchronized blocks of code. I need the two blocks of code not to be able to be running simultaneously in two or more different threads, but I would like to allow two or more different threads to run one of the blocks of code simultaneously. How can this be done in Java? To exemplify:
class HelloWorld {
method1() {
synchronized (?) { //block 'A'
//I want to allow 2+ threads to run this code block simultaneously
}
}
method2() {
synchronized (?) { //block 'B'
//this should block while another thread is running
//the synchronized block 'A'
}
}
I don't want both synchronized blocks to lock on the same object/class, because that would disallow the first block from being run by multiple threads simultaneously. However, it is the only way I know of to prevent block A and B from running simultaneously by 2 or more threads. There must be a way to achieve this.
I suggest to look into the ReadWriteLock respectively the implementing class ReentrantReadWriteLock. That thing is espeically designed to allow multiple "reader" threads; but only one "writer" thread.
If i read your question correctly, that is exactly what you are asking for. On the other hand, it might also be wise to step back and eloborate what the real problem is that you are trying to solve here.
Especially given the fact that the aforementioned lock works nicely with Java8, but saw problems in earlier version of Java.
Maybe something like:
private CommonStateSynchronizer synchronizer = new CommonStateSynchronizer();
public void method1() throws InterruptedException
{
synchronizer.run("method1", () -> {
// do method1
});
}
public void method2() throws InterruptedException
{
synchronizer.run("method2", () -> {
// do method2
});
}
public static class CommonStateSynchronizer
{
private final ReentrantReadWriteLock rw;
private final ReentrantReadWriteLock.ReadLock r; // hold read lock while executing in current state
private final ReentrantReadWriteLock.WriteLock w; // hold write lock while checking or changing state
private final Condition stateChanged;
private volatile String currentState; // do not modify unless holding write lock
public CommonStateSynchronizer()
{
rw = new ReentrantReadWriteLock(true);
r = rw.readLock();
w = rw.writeLock();
stateChanged = w.newCondition();
}
public void run(String state, Runnable runnable) throws InterruptedException {
w.lock();
while (!state.equals(currentState))
{
if (currentState == null)
{
currentState = state;
stateChanged.notifyAll();
break;
}
stateChanged.await();
}
assert state.equals(currentState);
// downgrade to concurrent read lock
r.lock();
w.unlock();
try
{
runnable.run();
}
finally
{
r.unlock();
w.lock();
if (rw.getReadLockCount() == 0)
{
currentState = null;
stateChanged.notifyAll();
}
w.unlock();
}
}
}
I'm reading "Java Concurrency in Practice" and trying to write a piece of code that will show that the class presented as an example in chapter 3.5.1 can indeed introduce problems.
public class Holder {
public int n;
public Holder(int n) {
this.n = n;
}
public void assertSanity() {
if (n != n) {
throw new AssertionError("sanity check failed!!");
}
}
}
It's said there that if used in the following way(I believe it's about the fact that the field is public, a concurrency problem may happen.
public Holder holder;
public void initialize() {
holder = new Holder(42);
}
So I've come up with this code to see if anything bad happens.
public class SanityCheck {
public Holder holder;
public static void main(String[] args) {
SanityCheck sanityCheck = new SanityCheck();
sanityCheck.runTest();
}
public void runTest() {
for (int i = 0; i < 100; i++) {
new Thread() {
#Override
public void run() {
while (true) {
if (holder != null) {
holder.assertSanity();
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
}
}
}
}.start();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
initialize();
}
public void initialize() {
holder = new Holder(42);
}
}
But nothing bad happens, no AssertionError has been thrown.
Could you please help me figure out why this code doesn't brake anything?
Thank you in advance for your time.
The fact that the code is not thread safe and could create concurrency issues does not mean that it will do so.
The Java Memory Model (JMM) says how a program must behave when it is properly synchronized. But it does not say much about how a program could behave when it is not.
For example, a JVM that would enforce sequential consistency would be compliant with the JMM and no concurrency issue would ever happen.
W.r.t. your specific example, it is very unlikely to break on an x86/hostpot combination.
It's said there that if used in the fallowing way(I believe it's about the fact that the field is public, a concurrency problem may happen.
Problem may happen, but there is no guarantee there will be any problems.
If you are using the Oracle JVM, AFAIK it treats interoperated code accesses as volatile. It is only once you compile the constructor and the checker than you might see a problem. Even then, I suspect you will have difficultly.
Shouldn't you be changing the value of n to cause something to break? In it's current form, I don't see how the AssertionError will ever be thrown, regardless of concurrency issues.
I expected something like this:
if (holder != null) {
holder.n = holder.n - 1;
holder.assertSanity();
}
I want to test if lazy initialization is thread-safe, so my code is below:
package LazyInit;
import java.util.Random;
public class UnThreadSafeLazyInit {
private ExpensiveObject instance = null;
public ExpensiveObject getInstance() {
if (null == instance) {
instance = new ExpensiveObject();
}
System.out.println("instance=" + instance);
return instance;
}
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
for (int i = 0; i < 5; i++) {
UnThreadSafeLazyInit init = new UnThreadSafeLazyInit();
Task t1 = init.new Task();
Task t2 = init.new Task();
t1.start();
t2.start();
try {
Thread.sleep(4000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(t1.getInstance() == t2.getInstance());
}
}
static class ExpensiveObject {
}
class Task extends Thread {
private ExpensiveObject instance = null;
private Random rand = new Random(47);
public void setInstance () {
this.instance = UnThreadSafeLazyInit.this.getInstance();
}
public ExpensiveObject getInstance() {
return instance;
}
#Override
public void run() {
// TODO Auto-generated method stub
try {
Thread.sleep(rand.nextInt(1000));
} catch (Exception e) {
e.printStackTrace();
}
setInstance();
}
}
}
In my code, every time I new two Thead task to call public ExpensiveObject getInstance(), in order to prove the two instance maybe not the same reference to ExpensiveObject since race Condition.
When I ran it, it always return true by t1.getInstance() == t1.getInstance().
As I know, if I don't synchronized the function public ExpensiveObject getInstance(), it could be return false since race Condition exists in Lazy Initialization.
I need to find out which code is error.
Thank you.
It is not thread safe, just by inspection of the code. The problem you have is that delays of many milli-seconds is an enormous time to a computer and you are very, very unlikely to see a problem with this type of testing.
For example, the typical delay between updating a volatile field and it being visible to other threads is around 5 nano-seconds. It is for about this long that your solution is not thread safe. You are waiting up up to 1,000,000,000 nano-seconds to see if you get an issue.
This is like trying to see if fireworks lasting 5 seconds went off, but closing your eyes 317 years before concluding there was no fireworks.
Why it is not thread safe has already been covered by others. But I wanted to comment on your title: "I want to test if lazy initialization is thread-safe".
You can't test that a piece of code is thread safe. You might be able to find a test that proves that it is not, but testing only can't prove thread safety:
your test might not interleave threads in a way that reproduces the problem
your test might introduce additional synchronization (for example System.out.println is synchronized) that hides the actual issues
the issue might only appear in a very rare scenario that a few test runs will probably not encounter
the issue might only appear on certain JVMs / CPUs and the fact that your tests "works" with one specific setup does anyway not prove anything
The easiest way would be to make ExpensiveObject a really expensive object:
public class ExpensiveObject {
public ExpensiveObject() {
System.out.println("I'm expensive!");
try {
Thread.sleep(2000L);
}
catch (InterruptedException e) {
}
System.out.println("See. It took 2 seconds to create me!");
}
}
Otherwise, the chance of entering into a rece condition is very small, especially since one thread is started after the other one, and thus calls setInstance() after the other one.
It's not Thread-safe. You're just lucky this time. Modify your code:
public ExpensiveObject getInstance() {
if (null == instance) {
System.out.println("old instance=" + instance);
instance = new ExpensiveObject();
System.out.println("new instance=" + instance);
}
return instance;
}
// In main
Thread.sleep(40); // Thread.sleep(4000);
// In run
Thread.sleep(rand.nextInt(10)); // Thread.sleep(rand.nextInt(1000));
I see a lot of false in my console with this code.
Here's what I want to do. Given a function
public void foo() {
}
I would like to have it end after certain time has elapsed. That is, imagine this is some kind of random generator which has to produce random objects that satisfy some difficult constraints and hence it may or may not succeed under a given time allotment. That is, the function may actually be something like this
public void foo() {
//task1
while(fails) {
//...
}
//task2
while(fails2) {
//...
}
//more tasks may follow, which use the data from the previous tasks to further try to satisfy difficult conditions
}
That is simply just an example. But the point is that the function consists of many while loops, many test cases, and lots of heavy computation.
The goal: I want to be able to say "run foo() and if 4 seconds has elapsed and foo() is still not done, then stop foo() immediately."
What I have tried: I have tried to include conditions on just about every line of foo() to see how much time has elapsed and to return out of the function if the 4 seconds has passed. But given how complicated foo() is, this is clearly very difficult to do code wise because this requires testing the time on every single line of the function.
My thought logic: I think this should be possible because there are functions that do this sort of thing, that terminate code regardless of the state, such as System.exit(1). That is the idea. I'd like to be able to call, from the outside, to have this function foo() terminate.
// foo method and global variables used
private static ArrayList<Integer> foo() {
// info class
class Info {
public boolean run, completed;
public ArrayList<Integer> list;
}
// declare info object, list
final Info info = new Info();
final Object wait = new Object();
// run a new thread
Thread t = new Thread(
new Runnable() {
// run method
#Override
public void run() {
// setup run
info.run = true;
info.completed = false;
info.list = new ArrayList<>();
// loop to modify list. Don't put a big piece of code that will
// take a long time to execute in here.
while(info.run) {
// example of what you should be doing in here:
info.list.add(1);
// and if you are done modifying the list, use:
break;
}
// done modifying list
info.completed = true;
synchronized(wait) {
wait.notify();
}
}
}
);
t.start();
// wait for four seconds, then return list
try {
synchronized(wait) {
wait.wait(4000);
}
} catch (InterruptedException e) { e.printStackTrace(); }
info.run = false;
return info.completed ? info.list : null;
}
// main method
public static void main(String[] args) {
// get list
ArrayList<Integer> list = foo();
System.out.println("Done!");
}
What the foo() method does?
Begins to modify the list it will eventually return
If the time took modifying this list exceeds four seconds, it will stop modifying the list and return the list.
It will return null if the list was stopped early.
It now only uses local variables!
Nice bonus, it will immediately return the list the second modifying it is done.
Submit it as a runnable to an executor service and call get on the returned future with the desired timeout. Then in the catch block for the timeout exception you can cancel the future.
EDIT: Code sample
import com.google.common.base.Throwables;
import java.util.concurrent.*;
public class ExecutorExample {
private static final ExecutorService executor = Executors.newSingleThreadExecutor();
public void example() {
Future<String> future = executor.submit(new Callable<String>() {
#Override
public String call() throws Exception {
return "Do your complicated stuff";
}
});
try {
future.get(4, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Throwables.propagate(e);
} catch (ExecutionException e) {
//handle
} catch (TimeoutException e) {
future.cancel(true);
}
}
}
Something like this will do the trick, but beware:
public static void main(String[] args){
Runnable fooRunner = new Runnable(){ public void run(){
foo();
}
Thread fooThread = new Thread(fooRunner);
fooThread.start();
Thread.sleep(4000);
fooThread.stop(); //warning -- this is deprecated!
}
The problem is that Thread.stop is deprecated.
Multi-threading in Java is fundamentally a cooperative endeavor. Because foo() may be manipulating shared state, probably protected by a lock that it currently owns, stopping it at an arbitrary point is potentially very dangerous and could lead to unpredictable failures, bugs, etc. later on in the program. (Indeed, since foo's return type is void, it must manipulate some shared state at some point in order to store its result.)
The language does provide a way to tell a thread that it should stop at the next convenient point: Thread.interrupt(), Thread.interrupted(), and InterruptedException. Your foo() method does need to check whether it's been interrupted periodically; that's the way it's done, and any higher-level library constructs (like Future.cancel()) rely on this.
You must enter into the hellish arena of writing threaded code.
http://docs.oracle.com/javase/tutorial/essential/concurrency/
Pseudo code (mutableboolean available in apache commons http://commons.apache.org/lang/download_lang.cgi)
...
final MutableBoolean finished = new MutableBoolean(false);
new Thread(new Runnable(){
public void run() {
doComplicatedStuff(finished);
}
}).start();
Thread.sleep(4000);
finished.setValue(true);
I have some code that I want to have some one time initialisation performed. But this code doesn't have a definite lifecycle, so my logic can be potentially invoked by multiple threads before my initialisation is done. So, I want to basically ensure that my logic code "waits" until initialisation is done.
This is my first cut.
public class MyClass {
private static final AtomicBoolean initialised = new AtomicBoolean(false);
public void initialise() {
synchronized(initialised) {
initStuff();
initialised.getAndSet(true);
initialised.notifyAll();
}
}
public void doStuff() {
synchronized(initialised) {
if (!initialised.get()) {
try {
initialised.wait();
} catch (InterruptedException ex) {
throw new RuntimeException("Uh oh!", ex);
}
}
}
doOtherStuff();
}
}
I basically want to make sure this is going to do what I think it's going to do -- block doStuff until the initialised is true, and that I'm not missing a race condition where doStuff might get stuck on a Object.wait() that will never arrive.
Edit:
I have no control over the threads. And I want to be able to control when all of the initialisation is done, which is why doStuff() can't call initialise().
I used an AtomicBoolean as it was a combination of a value holder, and an object I could synchronize. I could have also simply had a "public static final Object lock = new Object();" and a simple boolean flag. AtomicBoolean conveniently gave me both. A Boolean can not be modified.
The CountDownLatch is exactly what I was looking for. I also considered using a Sempahore with 0 permits. But the CountDownLatch is perfect for just this task.
That's a strange mix of library and built-in concurrency controls. Something like this is much cleaner:
public class MyClass {
private static final CountDownLatch latch = new CountDownLatch(1);
public void initialise() {
initStuff();
latch.countDown();
}
public void doStuff() {
try {
latch.await();
} catch (InterruptedException ex) {
throw new RuntimeException("Uh oh!", ex);
}
doOtherStuff();
}
}
A synchronized block will automatically block other threads. Just use a simple lock object + status variable:
public class MyClass {
private static boolean initialised;
private static final Object lockObject = new Object();
public void initialise() {
synchronized (lockObject) {
if (!initialised) {
initStuff();
initialised = true;
}
}
}
public void doStuff() {
initialise();
doOtherStuff();
}
}
The best may be to use a static initializer (as mentioned by SB):
public class MyClass {
public static void doInitialize() {
...
}
public void doStuff() {
doOtherStuff();
}
static {
doInitialize();
}
}
This will get executed once before any other code is allowed to be called. If you will always have to initialize anytime the class is used then there is no performance hit as the class will not be loaded until it is used. See the answers to this question for more details.
It this is right at startup, why not wait to start the other threads until the initialization is complete?
Also, you can do a thread-synchronized IsComplete boolean that is set to false until it is set to true by the initialization routine.
You're using AtomicBoolean always from inside a synchronized block. There's not much point to that since only one thread can access it. Atomic variables are intended for use in lock-free solutions - you can get and set the value as an uninterruptable unit.
I guess you are looking for a lock free solution once the intiialization has happened:
public class MyClass {
private static final AtomicBoolean initialised = new AtomicBoolean(false);
public void initialise() {
if (!intialized.get())
{
synchornized (this)
{
if (!initialized.getAndSet(true))
doInitialize();
}
}
}
public void doStuff() {
initialize();
doOtherStuff();
}
You could also do this with a simple volatile boolean which is actually a little more efficient than an AtomicBoolean.