Skip to content

Instantly share code, notes, and snippets.

@stantonk
Last active June 29, 2017 03:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stantonk/8915a1daeafbd73ff087fa849fc72043 to your computer and use it in GitHub Desktop.
Save stantonk/8915a1daeafbd73ff087fa849fc72043 to your computer and use it in GitHub Desktop.
Demonstrating classic thread safety issue with object reference being reused and passed to another thread
Thread-0 Person{name='Init', age=0}
Thread-0 Person{name='Init', age=0}
Thread-0 Person{name='Init', age=0}
main Person{name='Foo', age=-1356876606}
Thread-0 Person{name='Foo', age=-1356876606}
Thread-0 Person{name='Foo', age=-1356876606}
Thread-0 Person{name='Foo', age=-1356876606}
main Person{name='Bar', age=1050348248}
Thread-0 Person{name='Bar', age=1050348248}
Thread-0 Person{name='Bar', age=1050348248}
Thread-0 Person{name='Bar', age=1050348248}
main Person{name='Baz', age=-803476628}
Thread-0 Person{name='Baz', age=-803476628}
Thread-0 Person{name='Baz', age=-803476628}
Thread-0 Person{name='Baz', age=-803476628}
main Person{name='Foo', age=-293422591}
Thread-0 Person{name='Foo', age=-293422591}
Thread-0 Person{name='Foo', age=-293422591}
package com.github.stantonk.java_sandbox;
import java.util.Random;
public class ThreadSafetyViolationObjectReference {
public static class Person {
public String name;
public Integer age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("Person{");
sb.append("name='").append(name).append('\'');
sb.append(", age=").append(age);
sb.append('}');
return sb.toString();
}
}
public static void main(String[] args) {
Person p = new Person("Init", 0);
// This thread demonstrates
Thread thread = new Thread(() -> {
while (true) {
// notice, p is now shared across threads! mutations in the
// main thread will be visible in this thread as well
System.out.println(String.format("%s %s", Thread.currentThread().getName(), p));
sleep(1000);
}
});
thread.setDaemon(true);
thread.start();
String[] names = {"Foo", "Bar", "Baz"};
int i = 0;
while (true) {
sleep(3000);
p.name = names[i];
p.age = new Random().nextInt();
System.out.println(String.format("%s %s", Thread.currentThread().getName(), p));
i = (i % 2 == 0 && i != 0) ? 0 : i + 1;
}
}
private static void sleep(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment