Could anyone tell me how to accessing one method simultaneously with 2 thread, this method have 2 parameter and 2 synchronized block. and what I want is, one thread execute first synchronized block, and the other thread execute the second synchronized block.
public class myThread{
public static class TwoSums implements Runnable{
private int sum1 = 0;
private int sum2 = 0;
public void add(int a, int b){
synchronized(this){
sum1 += a;
String name = Thread.currentThread().getName();
System.out.println("Thread name that was accessing this code 1 : "+name);
}
synchronized(this){
sum2 += b;
String name = Thread.currentThread().getName();
System.out.println("Thread name that was accessing this code 2 : "+name);
}
}
#Override
public void run() {
add(10,20);
}
}
public static void main(String[] args) {
TwoSums task = new TwoSums();
Thread t1 = new Thread(task, "Thread 1");
Thread t2 = new Thread(task, "Thread 2");
t1.start();
t2.start();
}
}
This code containing some code from : http://tutorials.jenkov.com/java-concurrency/race-conditions-and-critical-sections.html
The instructions are processed sequentially by any thread and the synchronization blocks don't make any exception. The following code does what you are asking for but looks just as an exercise without any real meaningful application
public static class TwoSums implements Runnable {
private int sum1 = 0;
private int sum2 = 0;
public void add(int a, int b) {
if ("Thread 1".equals(Thread.currentThread().getName())) {
synchronized (this) {
sum1 += a;
String name = Thread.currentThread().getName();
System.out.println("Thread name that was accessing this code 1 : " + name);
}
}
if ("Thread 2".equals(Thread.currentThread().getName())) {
synchronized (this) {
sum2 += b;
String name = Thread.currentThread().getName();
System.out.println("Thread name that was accessing this code 2 : " + name);
}
}
}
#Override
public void run() {
add(10, 20);
}
}
In order to achieve that goal (I'm not going to discuss if what you're doing is right or wrong because I suppose that you're just learning how things work) you need to use the ReentranLock interface and its implementation Lock class:
Lock lock = new ReentrantLock();
You should declare this object in your TwoSum class and use the lock object inside of your add method. ReentrantLock interface has a method called tryLock which will try to get the lock of the object where it's called and it will return a boolean value true if it was successful or false otherwise. So for the first thread it will return true, but for the second one it will return false. So all you need to put is a validation
if(lock.tryLock()) //Execute block code 1
else // Execute block code 2
Related
The goal: So I have a runnable class ThisThat. I instantiate two threads of ThisThat. One prints "This" and one prints "That". The main class is not supposed to determine what it prints.
The question: how do I make a default constructor set two different outputs for two threads of the same class? What can be improved? How can I make it only print this or that instead of both simultaneously?
Desired end result would be a program that runs for about 10 seconds and prints either this or that 10 times. Current output is "this" "that" at the same time, waits about 10 seconds and then repeats 10 times.
import java.util.Random;
public class ThisThat implements Runnable {
private String output;
private int threadNum;
public ThisThat() {
output = "";
}
public ThisThat(int t_Num) {
threadNum = t_Num;
setThisOrThat(threadNum);
}
public void setThisOrThat(int num) {
if (num == 1) {
output = "this";
} else if (num == 2) {
output = "that";
} else {
Random random = new Random();
int randNum = random.nextInt((3) + 1);
setThisOrThat(randNum);
}
}
#Override
public void run() {
for (int i=1; i <= 10; i++) {
try {
System.out.println(getOutput());
Thread.sleep((int)(800));
}
catch(InterruptedException e) {
System.err.println(e);
}
}
}
public String getOutput() { return output; }
public void setOutput(String output) { this.output = output; }
}
class Main {
public static void main(String args[]) {
Thread thread1 = new Thread(new ThisThat(1));
Thread thread2 = new Thread(new ThisThat(2));
thread1.start();
thread2.start();
}
}
One solution is to update the constructor to not take in anything from Main, then create a static volatile or Atomic property within your ThisThat class that is basically a counter changing the values for each thread instance.
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.
This question already has answers here:
synchronized block for an Integer object
(3 answers)
Closed 6 years ago.
Edit:
I have already found the answer on the stack:
https://stackoverflow.com/a/16280842/3319557
I face a problem with synchronization. I have two following methods:
public synchronized void incrementCounter1() {
counter++;
}
public void incrementCounter2() {
synchronized (counter) {
counter++;
}
}
I test each of those (separately) in many threads. First method behaves as expected, but second (incrementCounter2) is wrong. Can somebody explain why is this happening?
I assume this method is well designed, as I found something lookalike in Java Concurrency in Practice. Snipped from this book:
#ThreadSafe
public class ListHelper<E> {
public List<E> list = Collections.synchronizedList(new ArrayList<E>());
...
public boolean putIfAbsent(E x) {
synchronized (list) {
boolean absent = !list.contains(x);
if (absent)
list.add(x);
return absent;
}
}
}
I use monitor from the Object I am modifying, exactly like in book.
Full code here:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class SynchronizationTest {
public static final int N_THREADS = 500;
public static final int N_Loops = 5000;
private Integer counter = 0;
Lock l = new ReentrantLock();
public void incrementCounter0() {
counter++;
}
public synchronized void incrementCounter1() {
counter++;
}
public void incrementCounter2() {
synchronized (counter) {
counter++;
}
}
public void incrementCounter3() {
try {
l.lock();
counter++;
} finally {
l.unlock();
}
}
private interface IncrementStrategy {
void use(SynchronizationTest t);
}
private static class IncrementingRunnable implements Runnable {
SynchronizationTest synchronizationTest;
IncrementStrategy methodToUse;
public IncrementingRunnable(SynchronizationTest synchronizationTest, IncrementStrategy methodToUse) {
this.synchronizationTest = synchronizationTest;
this.methodToUse = methodToUse;
}
#Override
public void run() {
for (int i = 0; i < N_Loops; i++) {
methodToUse.use(synchronizationTest);
}
}
}
public void test(IncrementStrategy methodToUse, String methodName) {
counter = 0;
Thread[] threads = new Thread[N_THREADS];
for (int i = 0; i < N_THREADS; i++) {
threads[i] = new Thread(new IncrementingRunnable(this, methodToUse));
threads[i].start();
}
for (int i = 0; i < N_THREADS; i++) {
try {
threads[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(methodName + " diff than expected " + (counter - N_THREADS * N_Loops));
}
public void test() {
test(t -> t.incrementCounter0(), "incrementCounter0 (expected to be wrong)");
test(t -> t.incrementCounter1(), "incrementCounter1");
test(t -> t.incrementCounter2(), "incrementCounter2");
test(t -> t.incrementCounter3(), "incrementCounter3");
}
public static void main(String[] args) {
new SynchronizationTest().test();
}
}
I know, that ExecutorService should be used, whole problem can be solved with AtomicLong, but it is not the point of this question.
Output of the code is:
incrementCounter0 (expected to be wrong) diff than expected -1831489
incrementCounter1 diff than expected 0
incrementCounter2 diff than expected -599314
incrementCounter3 diff than expected 0
PS.
If I add the field to SynchronizationTest
Object counterLock = new Object();
and change
incrementCounter2 to:
public void incrementCounter2() {
synchronized (counterLock) {
counter++;
}
}
Then incremetCounter2 works as expected.
You're synchronizing on different objects
incrementCounter1 synchronizes on this, while incrementCounter2 synchronizes on the counter Integer object itself.
You are trying to use two lock monitors (assuming counter is an Object, perhaps Integer?)
public class Foo {
// Uses instance of Foo ("this")
public synchronized void incrementCounter1() {
counter++;
}
public void incrementCounter2() {
// uses counter object as lock monitor
synchronized (counter) {
counter++;
}
}
}
I am not sure what you are trying to achieve with counter++ as it seems counter is of type Integer?
Few options to fix your problem:
Use a the same lock monitor
You might want to look into AtomicInteger
Use the lock API (e.g., ReentrantReadWriteLock)
Hideous.
synchronized void method(...
Synchronizes on the this Object.
synchronized(object) {
...
Synchronizes on object.
Now:
synchronized (counter) {
++counter;
must also synchronize on an Object, but counter is a primitive type, an int.
What happens, is that counter is boxed in an Integer.
When counter is 0 .. 127 the Integer object retrieved is everytime different, but shared. For say 1234 a new unique Integer object is created, and synchronized has no effect whatsoever. (Integer being immutable.)
I would call this almost a language error, something for FindBugs to find.
I'm a university student of Computer Science and I am familiar with threads in C.
However in Java the OOP makes Threads hard for me to understand.
I've written the following program and need to return values from the independent thread back to the main program.
The main program:
package main;
public class Main {
public static void main(String[] args) {
System.out.println(fibonacci(400));
}
public static int fibonacci(int x) {
Thread p1 = new Thread( new Fibonacci(x-1));
Thread p2 = new Thread( new Fibonacci(x-2));
p1.start();
p2.start();
int result = 0;
// Here I need the returns of the threads
// int result = thread_value1 + thread_value2;
return result;
}
}
The Fibonacci threads:
package main;
public class Fibonacci implements Runnable {
int result;
int x;
public Fibonacci(int parameter) {
x = parameter;
}
#Override
public void run() {
result = fib(x);
}
public int fib(int x) {
if(x == 1) return 1;
if(x == 2) return 1;
return fib(x-1) + fib(x-2);
}
}
The simplest way to achieve this is to save the results to a field in your Fibonacci objects and then read them from there. Note that since many threads will access this data, you need to synchronized access to these fields. In th e case of simple int values, adding the volatile modifier will be enough. It may also make the code clearer if you extend Thread instead of providing Runnable (but this is not neccessary). So your code could look something like this:
public class FibonacciThread extends Thread {
public volatile int result;
int x;
public FibonacciThread(int parameter) {
x = parameter;
}
#Override
public void run() {
result = fib(x);
}
public int fib(int x) {
if(x == 1) return 1;
if(x == 2) return 1;
return fib(x-1) + fib(x-2);
}
}
In main() you then do something like:
FibonacciThread p1 = new FibonacciThread(x-1);
FibonacciThread p2 = new FibonacciThread(x-2);
p1.start();
p2.start();
p1.join();
p2.join();
int result = p1.result + p2.result;
I'm skipping getters/setters and any fancy design for brevity's sake.
The call to Thread.join() is needed in order to wait for the thread to finish so that you can be sure that the result field was calculated before you read its value.
As noted by Sotirios Delimanolis in the comments, you can use Callable and ExecutorService for this, e.g. see this example
Another alternative that may be overkill here, but that is especially useful if the threads are producing more than one value, is to use a BlockingQueue or a ConcurrentLinkedQueue to communicate between threads. This is the basis behind libraries like Akka.
public class Main {
BlockingQueue<Integer> queue = new LinkedBlockingQueue();
public static int fibonacci(int x) {
Thread p1 = new Thread( new Fibonacci(x-1, queue));
Thread p2 = new Thread( new Fibonacci(x-2, queue));
p1.start();
p2.start();
// wait for queues to have values in them, then remove the values
int result = queue.take().intValue() + queue.take().intValue();
return result;
}
}
public class Fibonacci implements Runnable {
int x;
BlockingQueue<Integer> queue;
public Fibonacci(int parameter, BlockingQueue queueParam) {
x = parameter;
queue = queueParam;
}
#Override
public void run() {
// put output in queue
queue.offer(new Integer(fib(x)));
}
}
About Java synchronized, I try an example (from TLF-SOFT-VTC.java.6CFE), but it turns out wrong, why doesn't it synchronized ? The code :
public class InterferenceFix extends Thread {
String name;
static boolean isZero = true;
static int counter = 0;
public static void main(String arg[]) {
InterferenceFix one = new InterferenceFix("one");
InterferenceFix two = new InterferenceFix("two");
one.start();
two.start();
}
InterferenceFix(String nameString) {
name = nameString;
}
public void run() {
for (int i = 0; i < 100000; i++) {
update();
}
System.out.println(name + ": " + counter);
}
synchronized void update() {
if (isZero) {
isZero = false;
counter++;
} else {
isZero = true;
counter--;
}
}
}
Only your update method is synchronized which means that the loop can run simultaneously on both threads, only the update itself can't.
Also - the synchronized keyword actually locks on the object this and in your case, we're talking about 2 different instances which means they lock on different this. This means that actively - the threads are not interfering in any way with each other's work and they can both run simultaneously.
If that's indeed what you want you'd probably be better creating a static lock:
private static final Object lock = new lock();
And change update (or run) to this:
void update() {
synchronized (lock) {
if (isZero) {
isZero = false;
counter++;
} else {
isZero = true;
counter--;
}
}
}
If you need to sync the for loop, just use the lock in the same manner around the loop instead of inside update.
synchronized on an instance method does just serialize calls per instance, synchronized on a static method would do that per class, hence for all calls. So they have different lock objects. As one can guess now, a static synchronized method may be used to modify those static fields.