I want to create a java.util.stream.Stream that blocks on terminal actions and uses an arbitrary object for synchronization. The Stream's methods must do so themselves in a transparent way such that I could safely pass the Stream to code that is not aware of the synchronization.
Consider the following example:
void libraryMethod(Stream<Whatever> s) {
for (int i = 0; i < 10000000; ++i) { /* ... */ }
s.filter(Library::foo).forEach(Library::bar);
}
/* Elsewhere in my code */
Set<Whatever> aSet = Collections.synchronizedSet(...);
/* ... */
libraryMethod(new MyBlockingStream<>(set.stream(), set));
Before performing forEach, I want aSet's lock to be acquired by the MyBlockingStream itself and released only when forEach terminates. This should guarantee that I don't get ConcurrentModificationExceptions because other threads might want to modify the set. I can't use synchronized (aSet) on the entire libraryMethod because that would block aSet for much longer then needed.
Is it possible to do this? If so, are there any existing implementations that do that or do I have to write it myself?
Note: this question has nothing to do with how the Stream performs the actions - I don't care whether it's parallel or not. I am aware that there exist intrinsically unsynchronizable iterator() and spliterator() methods. I don't care about them either.
You could use a lock.
public class Example {
public static ReentrantLock lock = new ReentrantLock();
private static void sleep() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private static Runnable createRunnable() {
return () -> {
try {
Arrays.asList("a", "b", "c").stream().forEach(e -> {
if (!lock.isHeldByCurrentThread())
lock.lock();
sleep();
System.out.println(String.format("thread %s with element %s", Thread.currentThread().getId(), e));
});
} finally {
if(lock.isHeldByCurrentThread())
lock.unlock();
}
};
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(createRunnable());
Thread t2 = new Thread(createRunnable());
Thread t3 = new Thread(createRunnable());
t1.start();
t2.start();
t3.start();
System.out.println("join all threads");
t1.join();
t2.join();
t3.join();
}
}
The thread first to reach forEach will lock up all other threads.
Output in this case is
join all threads
thread 16 with element a
thread 16 with element b
thread 16 with element c
thread 15 with element a
thread 15 with element b
thread 15 with element c
thread 14 with element a
thread 14 with element b
thread 14 with element c
EDIT 1
As #Holger pointed out this will not work if the stream get nested. The inner stream will release the lock too early.
Here is what I ended up doing: https://gist.github.com/OLEGSHA/bda28ffaa4b24e64b94a8c30c3ad9b0c. These Stream wrappers synchronize all terminal operations using a provided object and wrap streams from intermediate operations.
This is essentially
public void forEach(Consumer<? super T> action) {
synchronized (monitor) {
parent.forEach(action);
}
}
for every terminal operation in Stream interface. IntStream, LongStream and DoubleStream versions included.
I think there must be a better solution though.
Related
package pkg_1;
public class ExpOnWaitMethod extends Thread {
static Double x = new Double(20);
public static void main(String[] args) {
ExpOnWaitMethod T1 = new ExpOnWaitMethod();
ExpOnWaitMethod T2 = new ExpOnWaitMethod();
T1.start();
T2.start();
}
public void run() {
Mag mag = new Mag();
synchronized (x) {
try {
for (int i = 1; i < 10; i++) {
mag.nop(Thread.currentThread());
x = i * 2.0;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Mag {
char ccc = 'A';
public void nop(Thread thr) throws InterruptedException {
System.out.print(ccc + " ");
ccc++;
if (thr.getState().toString().equalsIgnoreCase("runnable"))
Thread.currentThread().wait();
//thr.notify();
}
}
You need to hold the lock on the object you want to wait on (you can only call it within a synchronized block).
Also, calling wait on a Thread is very unusual and probably not what you want.
I am not sure what you are trying to do, but could you be confusing wait with sleep?
If you want to wait for another thread to finish, that would be anotherThread.join().
Before you call wait on an object, you must acquire that object's lock:
synchronized(obj)
{
obj.wait();
}
Your code is calling wait on a Thread object without acquiring the lock first.
I assume this is just a simplified test case to show your problem, but note that you probably want to be calling wait on an object that is accessible from all threads, not on the Thread objects themselves.
Someone should cite the API contract for java.lang.Object.wait(), which explains this directly. If a method raises an exception, read the documentation.
When in doubt, read the contract. (Bill McNeal on NewsRadio always kept his in his jacket pocket, a good metaphor for the JavaDoc API.. see "Crazy Prepared" under NewsRadio and ponder the imponderable.)
Look at this code:
public class VolatileTest {
private static boolean ready = false;
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(){
#Override
public void run() {
ready = true;
System.out.println("t2 thread should stop!");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread t2 = new Thread(){
#Override
public void run() {
while(!ready){
System.out.println("invoking..");
}
System.out.println("I was finished");
}
};
t1.start();
t2.start();
}
}
I think the result of this code maybe:
t2 thread should stop!
invoking..
I was finished
because of in the multithreading, when the t1 modify 'ready' variable to true,then I made t1 sleep. At the moment, I think, to t2 the 'ready' variable is false!!! because t1 thread is not stop, the variable in t1 is invisible in t2.
But in fact.. I test many times. the result is always this:
Am my idea is wrong?
First of all, despite calling your class VolatileTest, you are not actually using volatile anywhere in your code.
Since the ready variable is not declared as volatile AND you are accessing it without any explicit synchronization, the behavior is not specified. Specifically, the JLS does not say whether the assignment made in thread 1 to the ready variable will be visible within thread 2.
Indeed, there is not even guaranteed that the run() method for thread 1 will be called before the run() method for thread 2.
Now it seems that your code (as written!) is behaving in a way that is consistent with the write of true always being visible immediately. However, there is no guarantee that that "always" is actually always, or that this will be the case on every Java platform.
I would not be surprised if the syscall associated with sleep is triggering memory cache flushing before the second thread is scheduled. That would be sufficient to cause consistent behavior. Moreover, there is likely to be serendipitous synchronization1 due to the println calls. However, these are not effects you should ever rely on.
1 - Somewhere in the output stream stack for System.out, the println call is likely to synchronize on the stream's shared data structures. Depending on the ordering of the events, this can have the effect of inserting a happens before relationship between the write and read events.
As I mentioned in my comment, there are no guarantees. ("There is no guarantee what value thread t2 will see for ready, because of improper synchronization in your code. It could be true, it could be false. In your case, t2 saw true. That is consistent with "there is no guarantee what value t2 will see")
You can easily get your test to fail by running it multiple times.
When I run below code that does your test 100 times, I always get 14-22 "notReadies", so 14-22% of the cases you will not see the change to ready in Thread t2.
public class NonVolatileTest {
private static boolean ready = false;
private static volatile int notReadies = 0;
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 100; i++) {
ready = false;
// Copy original Thread 1 code from the OP here
Thread t2 = new Thread() {
#Override
public void run() {
if (!ready) {
notReadies++;
}
while (!ready) {
System.out.println("invoking..");
}
System.out.println("I was finished");
}
};
t1.start();
t2.start();
// To reduce total test run time, reduce the sleep in t1 to a
// more suitable value like "100" instead of "5000".
t1.join();
t2.join();
}
System.out.println("Notreadies: " + notReadies);
}
}
I have 4 threads each trying to find the max value in a linked list.
This is my thread class:
public class MyThread extends Thread {
LinkedList<Integer> list;
int max = Integer.MIN_VALUE;
public MyThread(LinkedList<Integer> list) {
this.list = list;
}
public void run() {
synchronized (list) { /* If I don't synchronize list, I get a NoSuchElementException at list.remove() */
while (!list.isEmpty()) {
int num = list.remove();
if (num > max) {
max = num;
}
}
}
}
}
And here is the class with the main method:
public class Application {
public static void main(String args[]) throws InterruptedException {
LinkedList<Integer> list = new LinkedList<Integer>();
for (int i = 0; i < 10; i++) {
list.add(i);
}
MyThread t1 = new MyThread(list);
MyThread t2 = new MyThread(list);
MyThread t3 = new MyThread(list);
MyThread t4 = new MyThread(list);
t1.start();
t2.start();
t3.start();
t4.start();
t1.join();
t2.join();
t3.join();
t4.join();
System.out.println(t1.max);
System.out.println(t2.max);
System.out.println(t3.max);
System.out.println(t4.max);
}
}
In the above code, I have to synchronize the list variable within the run method or else I'll get a NoSuchElementException at list.remove(). Why is this the case?
Doesn't each thread have it's own list so there is no thread interference?
Thanks
I will address a different part of your question that #Rishi addressed:
Doesn't each thread have it's own list so there is no thread interference?
The simple answer is: No, it does not. In Java, when you pass an object of class type to a constructor or method, you aren't passing the obejct itself but rather a pointer to it. If you want to pass a separate copy of the linked list to each thread, you need to use LinkedList#Clone.
If you use clone, then when a thread removes one integer from its linked list, it will not be removed from the other linked lists. To properly paralellize this, you should use a standard array with all of your numbers and assign a segment of this array to each thread (ie. thread 1 does 0-9, thread 2 does 10-19, thread 3 does 20-29, etc.). The array's contents will be visible to any threads created after the contents are deposited in the array.
I should also note that you should not extend Thread. Instead, extend Runnable and pass it to a thread. Furthermore, an array(list) would be better than 4 separate variables as it allows you to easily change the number of threads later.
LinkedList is not thread-safe. Hence it would need external synchronization if you operate on LinkedList with more than one thread.
You can use BlockingQueue, whose poll() method would come handy in this case.
Is there anything wrong with the thread safety of this java code? Threads 1-10 add numbers via sample.add(), and Threads 11-20 call removeAndDouble() and print the results to stdout. I recall from the back of my mind that someone said that assigning item in same way as I've got in removeAndDouble() using it outside of the synchronized block may not be thread safe. That the compiler may optimize the instructions away so they occur out of sequence. Is that the case here? Is my removeAndDouble() method unsafe?
Is there anything else wrong from a concurrency perspective with this code? I am trying to get a better understanding of concurrency and the memory model with java (1.6 upwards).
import java.util.*;
import java.util.concurrent.*;
public class Sample {
private final List<Integer> list = new ArrayList<Integer>();
public void add(Integer o) {
synchronized (list) {
list.add(o);
list.notify();
}
}
public void waitUntilEmpty() {
synchronized (list) {
while (!list.isEmpty()) {
try {
list.wait(10000);
} catch (InterruptedException ex) { }
}
}
}
public void waitUntilNotEmpty() {
synchronized (list) {
while (list.isEmpty()) {
try {
list.wait(10000);
} catch (InterruptedException ex) { }
}
}
}
public Integer removeAndDouble() {
// item declared outside synchronized block
Integer item;
synchronized (list) {
waitUntilNotEmpty();
item = list.remove(0);
}
// Would this ever be anything but that from list.remove(0)?
return Integer.valueOf(item.intValue() * 2);
}
public static void main(String[] args) {
final Sample sample = new Sample();
for (int i = 0; i < 10; i++) {
Thread t = new Thread() {
public void run() {
while (true) {
System.out.println(getName()+" Found: " + sample.removeAndDouble());
}
}
};
t.setName("Consumer-"+i);
t.setDaemon(true);
t.start();
}
final ExecutorService producers = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
final int j = i * 10000;
Thread t = new Thread() {
public void run() {
for (int c = 0; c < 1000; c++) {
sample.add(j + c);
}
}
};
t.setName("Producer-"+i);
t.setDaemon(false);
producers.execute(t);
}
producers.shutdown();
try {
producers.awaitTermination(600, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
sample.waitUntilEmpty();
System.out.println("Done.");
}
}
It looks thread safe to me. Here is my reasoning.
Everytime you access list you do it synchronized. This is great. Even though you pull out a part of the list in item, that item is not accessed by multiple threads.
As long as you only access list while synchronized, you should be good (in your current design.)
Your synchronization is fine, and will not result in any out-of-order execution problems.
However, I do notice a few issues.
First, your waitUntilEmpty method would be much more timely if you add a list.notifyAll() after the list.remove(0) in removeAndDouble. This will eliminate an up-to 10 second delay in your wait(10000).
Second, your list.notify in add(Integer) should be a notifyAll, because notify only wakes one thread, and it may wake a thread that is waiting inside waitUntilEmpty instead of waitUntilNotEmpty.
Third, none of the above is terminal to your application's liveness, because you used bounded waits, but if you make the two above changes, your application will have better threaded performance (waitUntilEmpty) and the bounded waits become unnecessary and can become plain old no-arg waits.
Your code as-is is in fact thread safe. The reasoning behind this is two part.
The first is mutual exclusion. Your synchronization correctly ensures that only one thread at a time will modify the collections.
The second has to do with your concern about compiler reordering. Youre worried that the compile can in fact re order the assigning in which it wouldnt be thread safe. You dont have to worry about it in this case. Synchronizing on the list creates a happens-before relationship. All removes from the list happens-before the write to Integer item. This tells the compiler that it cannot re order the write to item in that method.
Your code is thread-safe, but not concurrent (as in parallel). As everything is accessed under a single mutual exclusion lock, you are serialising all access, in effect access to the structure is single-threaded.
If you require the functionality as described in your production code, the java.util.concurrent package already provides a BlockingQueue with (fixed size) array and (growable) linked list based implementations. These are very interesting to study for implementation ideas at the very least.
I have been trying to solve a problem involving thread communication using wait() and notify(). Basically i have 2 threads T1 and T2 and i want them to be executed in the following order
T1 , T2, T1, T2 ..... How can i achieve that?
Actual Problem: There are 2 threads T1 - which prints odd numbers (say 1 - 100) and T2 - which prints even numbers (1 - 100). Now, the output should be 1, 2, 3, 4 , 5 , .... 100
You describe a Producer-Consumer pattern.
It's java implementations described in numerous java books including M.Grand "Patterns in Java. Volume I" and "Java 2: The Complete Reference" by Naughton and Schildt.
Basic idea: both threads should use 1 monitor (i.e. their code should be inside synchronized(monitor) {} blocks). You also need some flag variable which should indicate which of two threads should work at the moment.
When one of your threads is inside synchronized block it should check flag variable whether it's his turn to do the job. If yes, let it work and then change flag value and then notify all waiting threads. If no, then it should wait.
Look at the java.util.concurrent package, specifically the Exchanger
You're trying to parallelize a multistep process right? If so, see my answer here for an approach and some working code to do that. The answer involves an ExecutorService (or two) and one or more work queues.
For this approach, your processing needs to be able to fit into a Runnable, along with intermediate state information for the processing. You feed each step to the ExecutorService as a Runnable, which will add a second Runnable to perform the next step. This maintains the order of execution, but lets you effectively run as many threads as you wish in parallel.
:EDIT:
As another has suggested, the Exchanger library class can be used for this if you explicitly want to limit processing to 2 threads. I prefer the above approach because it maintains order of execution and allows you to use the modern 4-core (and 8-core) systems fully. It should also reduce synchronization a bit.
If T1 and T2 are 2 different implementations of the Runnable interface, with T1 being a thread that prints just odd numbers (1,3,...) and T2 being one that prints even number (1,2.....), this can be done by using the wait() and notify() methods on a shared monitor. The important thing is for each thread to check for a shared flag before printing its value. The below code works;
//The shared monitor
public class Mutex {
public static boolean oddFlag;
}
//The Thread that is supposed to print Odd numbers (assuming an upper limit of 99)
public class OddPrinter implements Runnable {
private Mutex mutex;
public OddPrinter(Mutex mutex) {
this.mutex = mutex;
}
public synchronized void run() {
System.out.println("Started Thread: OddPrinter");
int i;
for(i=1; i<100; i+=2 ) {
synchronized (mutex) {
while(!Mutex.oddFlag) {
try {
mutex.wait();
} catch (InterruptedException ie) {
Thread.currentThread().interrupted();
}
}
if(Mutex.oddFlag == true) {
System.out.println("Print from OddPrinter: "+i);
Mutex.oddFlag = false;
mutex.notify();
}
}
}
System.out.println("Finished Thread: OddPrinter: "+i);
}
}
//The Thread that is supposed to print Odd numbers (assuming an upper limit of 98)
public class EvenPrinter implements Runnable {
private Mutex mutex;
public EvenPrinter(Mutex mutex) {
this.mutex = mutex;
}
public synchronized void run() {
System.out.println("Started Thread: EvenPrinter");
int i;
for(i=2; i<100; i+=2) {
synchronized (mutex) {
while(Mutex.oddFlag) {
try {
mutex.wait();
} catch (InterruptedException ie) {
Thread.currentThread().interrupted();
}
}
if(!(Mutex.oddFlag == true)) {
System.out.println("Print from EvenPrinter: "+i);
Mutex.oddFlag = true;
mutex.notify();
}
}
}
System.out.println("Finished Thread: EvenPrinter: "+i);
}
}
//The test harness that executes the threads
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class NumberPrinterTest {
public static void main(String[] args) throws Exception{
ExecutorService es = Executors.newFixedThreadPool(2);
Mutex mutex = new Mutex();
OddPrinter op = new OddPrinter(mutex);
EvenPrinter ep = new EvenPrinter(mutex);
Mutex.oddFlag = true;
es.execute(op);
es.execute(ep);
if(null != es){
es.shutdown();
try {
es.awaitTermination(1, TimeUnit.MINUTES);
} catch (InterruptedException e) {
Thread.currentThread().interrupted();
}
}
}
}