Here is my code:
public class MyRunnableClass implements Runnable {
static int x = 25;
int y = 0;
private static final Object sharedLock = new Object();
#Override
public void run() {
while(x>0){
someMethod();
}
}
public synchronized void someMethod(){
synchronized (sharedLock){
x--;
y++;
}
}
}
and the test class:
public class MyRunnableClassTest {
public static void main(String[] args) throws InterruptedException {
MyRunnableClass aa = new MyRunnableClass();
MyRunnableClass bb = new MyRunnableClass();
Thread a = new Thread(aa);
Thread b = new Thread(bb);
a.start();
b.start();
a.join();
b.join();
System.out.println(aa.y + bb.y);
}
}
When I run this code as it is I see output 25 which is fine, but when x is 250, I see 251.. Why? Why not 250?
You have to extend the synchronized scope, so that is also covers the read operation on x:
#Override
public void run() {
for (;;) {
synchronized (sharedObject) {
if (x <= 0) break;
someMethod();
}
}
}
Coincidence. The same thing could happen with 25, just like any other number.
For example, during execution of
while(x>0){
someMethod();
}
which is not synchronized over, after a bunch of looping, let's take x to be 1. The first thread starts iterating (enters the body), then threads switch, the second thread sees x is 1, so enters the loop body as well. Both will increment their count and their sum will be equal to one more than the original x value.
This is a race condition and you just happen to see the consequences more easily with larger numbers.
When you are doing:
while(x>0){
someMethod();
}
Let's say x = 1 and:
Thread A evaluates x > 0 to true, and enters the loop.
Let's say Thread A gets interrupted before the next line executes.
Thread B will also evaluates x > 0 to true and enter the loop.
Both will decrement x one after the other and increment their y.
To solve this, the check for x > 0 must be in the lock as well.
Ex:
public class MyRunnableClass implements Runnable {
static int x = 25;
int y = 0;
private static final Object sharedLock = new Object();
#Override
public void run() {
while(x>0){
someMethod();
}
}
public synchronized void someMethod(){
synchronized (sharedLock){
if(x > 0){
x--;
y++;
}
}
}
}
Sometimes, both Thread a and Thread b can call someMethod() because x was 1. One Thread locks the sharedLock, makes x equal to 0, y equal to 250 and then release the sharedLock, at which point the other thread calls someMethod() and makes y equal to 251 and x equal to -1.
You could also solve that problem with AtomicInteger:
import java.util.concurrent.atomic.AtomicInteger;
public class MyRunnableClass implements Runnable {
private static final AtomicInteger xHolder = new AtomicInteger(25);
int y = 0;
#Override
public void run() {
while (xHolder.decrementAndGet() >= 0) {
y++;
}
}
public static void main(String[] args) throws InterruptedException {
MyRunnableClass aa = new MyRunnableClass();
MyRunnableClass bb = new MyRunnableClass();
Thread a = new Thread(aa);
Thread b = new Thread(bb);
a.start();
b.start();
a.join();
b.join();
System.out.println(aa.y + bb.y);
}
}
Or with some extended parallelism to test:
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
public class MyRunnableClass implements Callable<Integer> {
private static final AtomicInteger xHolder = new AtomicInteger(250000);
int y = 0;
#Override
public Integer call() throws Exception {
while (xHolder.decrementAndGet() >= 0) {
y++;
}
System.out.println(Thread.currentThread().getName() + " returns " + y);
return y;
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService executorService = Executors.newCachedThreadPool();
ExecutorCompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(
executorService);
int parallelism = 5;
for (int i = 0; i < parallelism; ++i) {
completionService.submit(new MyRunnableClass());
} // for
int ySum = 0;
for (int j = 0; j < parallelism; ++j) {
Future<Integer> future = completionService.take();
ySum += future.get();
} // for
System.out.println(ySum);
executorService.shutdown();
}
}
Output:
pool-1-thread-3 returns 26619
pool-1-thread-5 returns 0
pool-1-thread-1 returns 104302
pool-1-thread-2 returns 95981
pool-1-thread-4 returns 23098
250000
Related
public class ClassTest extends Thread{
public static Object lock = new Object();
public static LinkedList<Integer> stack;
public SortedSet<Integer> set= new TreeSet<>();
#Override
public void run(){
synchronized(lock){
// try{
// this.wait();
// }
// catch(Exception e){
// e.printStackTrace();
// }
while(!stack.isEmpty()){
set.add(stack.pop());
this.yield();
// this.notifyAll();
}
}
}
When i start() 5 Threads why just first one pop all elements and others do not pop anyone?
I tried to use wait() and notify() methods, but that didn't help..
The method yield does not release locks. The very first thread that enters the synchronized block will keep other threads from entering until the stack is empty and the lock is released.
Here is an example that does what you want using LinkedBlockingDeque.
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.LinkedBlockingDeque;
class Main {
static final LinkedBlockingDeque<Integer> stack = new LinkedBlockingDeque<>();
static class Poller implements Runnable {
final Set<Integer> set = new HashSet<>();
#Override
public void run() {
Integer elem = stack.poll();
while (elem != null) {
set.add(elem);
System.out.printf("%s: %d\n", Thread.currentThread().getName(), elem);
elem = stack.poll();
}
}
}
public static void main(String args[]) {
for (int i = 0; i < 100; i++) {
stack.push(i);
}
for (int i = 0; i < 5; i++) {
new Thread(new Poller()).start();
}
}
}
Now I'm struggling with the task from the title. I create X threads, each of them prints Y equal digits (getting from constructor, for example "11111", "222222" etc) for Z times in cycle. So the result looks like:
111111111
222222222
333333333
111111111
222222222
333333333
for X = 3, Y = 9 and Z = 2.
Firstly I've solved this issue using sleep, interrupt and passing "next" thread to the constructor of previous one. One interrupts another etc. Next step is to get the same output using wait/notify instead sleep and interrupt. As far as I can see, it's neccesary to create the shared monitor object, to invoke wait after every printing and in a some moment " I should invoke notifyAll.
Current code is:
public class PrinterController {
private static final int THREADS_NUMBER = 5;
public static void main(String[] args) {
Printer[] printers = new Printer[THREADS_NUMBER];
for (int i = 0; i < THREADS_NUMBER; i++) {
printers[i] = new Printer(i);
printers[i].start();
}
}
}
public class Printer extends Thread {
private static int portion = 10;
private static int totalNumber = 100;
private int digit;
private static final Object monitor = new Object();
public Printer(int digit) {
this.digit = digit;
}
#Override
public void run() {
synchronized (monitor) {
int portionsNumber = totalNumber / portion;
for (int i = 0; i < portionsNumber; i++) {
printLine();
try {
monitor.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
private void printLine() {
for (int j = 0; j < portion; j++) {
System.out.print(digit);
}
System.out.println();
}
}
Could you help to improve it? I found similar tasks but they don't contain appropriate answers. Thanks.
Final solution based on the Nadir's answer:
public class Printer extends Thread {
private static int portion = 10;
private static int totalNumber = 100;
private int digit;
static Object monitor = new Object();
static Integer counter = 0;
public Printer(int digit) {
this.digit = digit;
}
#Override
public void run() {
int portionsNumber = totalNumber / portion;
for (int i = 0; i < portionsNumber; i++) {
synchronized (monitor) {
while (digit != counter) {
try {
monitor.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
printLine();
monitor.notifyAll();
}
}
}
private void printLine() {
for (int j = 0; j < portion; j++) {
System.out.print(digit);
}
System.out.println();
counter = (counter + 1) % PrinterController.THREADS_NUMBER;
}
}
It can be accomplished with a class used to synchronize the threads (and even make sure they are orderer). All threads would share the same instance.
public class Synchronizer
{
private int nextThread;
private int maxNumThreads;
public Synchronizer(int numThreads)
{
maxNumThreads = numThreads;
nextThread = 0;
}
public void doSync(int threadId) throws Exception
{
synchronized(this)
{
while(nextThread != threadId)
{
wait();
}
}
}
public void threadDone(int threadId) throws Exception
{
synchronized(this)
{
nextThread = (threadId + 1) % maxNumThreads;
notifyAll();
}
}
}
On your thread's run(), you would call doSync() before printing anything. Then you would put the code for printing, and afterwards, you would call threadDone(), allowing the next thread to be released. The id is used to enforce an order.
Im trying to make 2 threads that read/write to a counter using thread safe methods.
I have written some code to try test this but the read thread just reads the counter at its max (1000)
Main:
public static void main(String[] args) {
Counter c = new Counter();
Thread inc = new Increment(c);
Thread read = new Read(c);
inc.start();
read.start();
}
Counter:
public class Counter {
private int count;
public Counter() {
count = 0;
}
public synchronized void increment() {
count++;
}
public synchronized int getVal() {
return count;
}
}
Increment:
public class Increment extends Thread {
private static final int MAX = 1000;
private Counter myCounter;
public Increment(Counter c) {
myCounter = c;
}
public void run() {
for (int i = 0; i < MAX; i++) {
myCounter.increment();
}
}
}
Read:
public class Read extends Thread {
private static final int MAX = 1000;
private Counter myCounter;
public Read(Counter c) {
myCounter = c;
}
public void run() {
for (int i = 0; i < MAX; i++) {
System.out.println(myCounter.getVal());
}
}
}
Would I be better off using Atomic Integer to hold the value of the counter to allow me to safely increment it and get the value?
Your code is perfectly fine as is. It just so happened that your increment thread finished all its increments before the read thread got a chance to read. 1,000 increments takes almost no time at all.
If you want interleave execution of Read thread and Increment thread much more often then the natural operating system thread pre-emption, just make each thread give up their lock (by calling <lockedObject>.wait() followed by <lockedObject>.notify() or notifyAll() in the respective run() methods:
[In Reader]:
public void run() {
for (int i = 0; i < MAX; i++) {
synchronized (myCounter) {
System.out.println(myCounter.getVal());
try {
myCounter.wait(0L, 1);
myCounter.notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
[In Increment]:
public void run() {
for (int i = 0; i < MAX; i++) {
synchronized (myCounter) {
myCounter.increment();
try {
myCounter.wait(0L, 1);
myCounter.notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Upping the MAX constant to 1_000_000_000 (1 billion) made the treads interleave as well every now and then (on my machine interleave happened just by gazing at few printouts between 150 and 400_000 iterations).
I read now Thinking in Java, chapter about synchronization and there is an example I cannot understand.
public abstract class IntGenerator {
private volatile boolean canceled = false;
public abstract int next();
public void cancel() {
canceled = true;
}
public boolean isCanceled() {
return canceled;
}
}
public class EvenGenerator extends IntGenerator {
private int currentEvenValue = 0;
final Object object = new Object();
#Override
public int next() {
++currentEvenValue;
++currentEvenValue;
return currentEvenValue;
}
public static void main(String[] args) {
EvenChecker.test(new EvenGenerator());
}
}
public class EvenChecker implements Runnable {
private IntGenerator generator;
private final int id;
public EvenChecker(IntGenerator generator, int id) {
this.generator = generator;
this.id = id;
}
#Override
public void run() {
while (!generator.isCanceled()) {
int val = generator.next();
if (val % 2 != 0) {
System.out.println(val + " odd");
generator.cancel();
}
}
}
public static void test(IntGenerator generator, int count) {
System.out.println("To finish press Ctrl + C");
final ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < count; i++) {
executorService.execute(new EvenChecker(generator, i));
}
}
public static void test(IntGenerator generator) {
test(generator, 10);
}
}
And example output is:
1239 odd
1237 odd
1239 odd
And I understand it. It means that 3 threads read currentValue after first increment.
Solution of this problem is:
public class SynchronizedEvenGenerator extends IntGenerator {
private int currentEvenValue = 0;
#Override
public synchronized int next() {
++currentEvenValue;
Thread.yield();
++currentEvenValue;
return currentEvenValue;
}
public static void main(String[] args) {
EvenChecker.test(new SynchronizedEvenGenerator());
}
}
Now the program is working infinity without the mistake.
I tried to synchronize only increments in this way:
public class SynchronizedEvenGenerator extends IntGenerator {
private int currentEvenValue = 0;
#Override
public int next() {
synchronized (this) {
++currentEvenValue;
Thread.yield();
++currentEvenValue;
}
return currentEvenValue;
}
public static void main(String[] args) {
EvenChecker.test(new SynchronizedEvenGenerator());
}
}
But now example out put is:
345 odd
And I cannot understand why is it possible to read the odd value of currentValue if both increments are synchronized and any thread cannot read currentValue between first and second increment.
Why I get this output. How does work synchronized?
Your final example's return currentEventValue; statement is not inside the synchronized block. So, suppose thread A and thread B both call next():
Thread A:
Synchronizes,
Increments currentEventValue (value now is odd)
Increments currentEventValue (value is even again)
leaves the synchronized block.
Thread B:
Synchronizes
Increments currentEventValue (value now is odd)
Thread A:
returns currentEventValue (odd)
Thread B:
Increments currentEventValue (value is even again)
Leaves the synchronized block.
returns an even value.
currentEvenValue is 342
thread 1 enters the synchronized block
thread 2 tries to enter the synchronized block but must wait
thread 1 increments currentEvenValue twice, so the value is now 344
thread 1 leaves the synchronized block
thread 2 enters the synchronized block and increments currentEvenValue a first time, so the value is now 345
thread 1 reads the value of currentEvenValue, returns it, and prints it: 345
The rule is simple: all accesses to a shared state, read or write, must be synchronized.
I have a program where 3 Threads are trying to print numbers in sequence from 1 to 10. I am using a CountDownLatch to keep keep a count.
But the program stops just after printing 1.
Note: I am aware that using AtomicInteger instead of Integer can work. But I am looking to find out the issue in the current code.
public class Worker implements Runnable {
private int id;
private volatile Integer count;
private CountDownLatch latch;
public Worker(int id, Integer count, CountDownLatch latch) {
this.id = id;
this.count = count;
this.latch = latch;
}
#Override
public void run() {
while (count <= 10) {
synchronized (latch) {
if (count % 3 == id) {
System.out.println("Thread: " + id + ":" + count);
count++;
latch.countDown();
}
}
}
}
}
Main program:
public class ThreadSequence {
private static CountDownLatch latch = new CountDownLatch(10);
private volatile static Integer count = 0;
public static void main(String[] args) {
Thread t1 = new Thread(new Worker(0, count, latch));
Thread t2 = new Thread(new Worker(1, count, latch));
Thread t3 = new Thread(new Worker(2, count, latch));
t1.start();
t2.start();
t3.start();
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Edited program with AtomicInteger:
public class ThreadSequence {
private static AtomicInteger atomicInteger = new AtomicInteger(1);
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new WorkerThread(0, atomicInteger));
Thread t2 = new Thread(new WorkerThread(1, atomicInteger));
Thread t3 = new Thread(new WorkerThread(2, atomicInteger));
t1.start();
t2.start();
t3.start();
t1.join();
t2.join();
t3.join();
System.out.println("Done with main");
}
}
public class WorkerThread implements Runnable {
private int id;
private AtomicInteger atomicInteger;
public WorkerThread(int id, AtomicInteger atomicInteger) {
this.id = id;
this.atomicInteger = atomicInteger;
}
#Override
public void run() {
while (atomicInteger.get() < 10) {
synchronized (atomicInteger) {
if (atomicInteger.get() % 3 == id) {
System.out.println("Thread:" + id + " = " + atomicInteger);
atomicInteger.incrementAndGet();
}
}
}
}
}
But the program stops just after printing 1.
No this is not what happens. None of the threads terminate.
You have a own count field in every worker. Other threads do not write to this field.
Therefore there is only one thread, where if (count % 3 == id) { yields true, which is the one with id = 0. Also this is the only thread that ever modifies the count field and modifying it causes (count % 3 == id) to yield false in subsequent loop iterations, causing an infinite loop in all 3 threads.
Change count to static to fix this.
Edit
In contrast to Integer AtomicInteger is mutable. It is a class that holds a int value that can be modified. Using Integer every modification of the field replaces it's value, but using AtomicInteger you only modify the value inside the AtomicInteger object, but all 3 threads continue using the same AtomicInteger instance.
Your "count" is a different variable for each thread, so changing it in one thread doesn't affect the rest, and so they are all waiting for it to change, without any one that can do it.
Keep the count as static member in Worker class - common for all object in the class.
You can use below code to print sequential numbers using multiple threads -
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class ThreadCall extends Thread {
private BlockingQueue<Integer> bq = new ArrayBlockingQueue<Integer>(10);
private ThreadCall next;
public void setNext(ThreadCall t) {
this.next = t;
}
public void addElBQ(int a) {
this.bq.add(a);
}
public ThreadCall(String name) {
this.setName(name);
}
#Override
public void run() {
int x = 0;
while(true) {
try {
x = 0;
x = bq.take();
if (x!=0) {
System.out.println(Thread.currentThread().getName() + " =>" + x);
if (x >= 100) System.exit(0); // Need to stop all running threads
next.addElBQ(x+1);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
int THREAD_COUNT = 10;
List<ThreadCall> listThread = new ArrayList<>();
for (int i=1; i<=THREAD_COUNT; i++) {
listThread.add(new ThreadCall("Thread " + i));
}
for (int i = 0; i < listThread.size(); i++) {
if (i == listThread.size()-1) {
listThread.get(i).setNext(listThread.get(0));
}
else listThread.get(i).setNext(listThread.get(i+1));
}
listThread.get(0).addElBQ(1);
for (int i = 0; i < listThread.size(); i++) {
listThread.get(i).start();
}
}
}
I hope this will resolve your problem