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.
Related
ProdCom.java (driver class)
import static java.lang.System.out;
public class ProdCom{
static int full = 50;
static int mutx = 0;
static int empty = 0;
static int currentSize = 0;
public static void acquire(){
while (mutx == 1);
mutx++;
}
public static void release(){
mutx--;
}
public static void main(String args[]){
Thread t = new Thread(new Producerr());
Thread t1 = new Thread(new Consumerr());
t.start();
t1.start();
}
}
Producerr.java
class Producerr implements Runnable{
public void wwait(){
while (ProdCom.currentSize >= ProdCom.full){
}
} public void signal(){
ProdCom.currentSize++;
}
public void run(){
do{
this.wwait();
ProdCom.acquire();
out.println("Num elements" + ProdCom.currentSize);
out.println("producing!");
ProdCom.release();
this.signal();
} while (true);
}
}
Consumerr.java
class Consumerr implements Runnable{
public void wwait(){
while (ProdCom.currentSize <= 0){
out.println("inside consumer wait: ");
out.println("number of elements: " + ProdCom.currentSize);
}
} public void signal(){
ProdCom.currentSize--;
}
public void run(){
do{
this.wwait();
ProdCom.acquire();
out.println("Num elements" + ProdCom.currentSize);
out.println("Consuming!");
ProdCom.release();
this.signal();
} while (true);
}
}
Above is my solution to the consumer-producer problem. The driver class ProdCom has variables full, empty and mutx for controlling producer t and consumer t1's access to the variable currentSize (Thus simulating the current number of items in a buffer). But when I run the code, the output seems to indicate t1 and t aren't taking turns to change currentSize, instead one of them repeats forever and gets stuck...I'm wondering why? Thanks.
I've improved your code a bit, and you'll notice that many of the concepts mentioned by Joni are considered.
ProdCom.java
import java.lang.*;
public class ProdCom{
static final int FULL = 50;
static final int EMPTY = 0;
static volatile int mutx = 0;
static volatile int currentSize = 0;
static Object lockObject = new Object();
public static void acquire(){
/* since mutx is defined volatile, the spinlock works,
but you reconsider this approach. There are cheaper
methods of heating the room */
while (mutx == 1);
mutx++;
}
public static boolean isEmpty() {
synchronized(lockObject) {
if (currentSize <= EMPTY) return true;
return false;
}
}
public static boolean isFull() {
synchronized(lockObject) {
if (currentSize >= FULL) return true;
return false;
}
}
public static int getCurrentSize() {
synchronized(lockObject) {
return currentSize;
}
}
public static void release(){
mutx--;
}
public static void incCurrentSize()
{
synchronized(lockObject) {
currentSize++;
}
}
public static void decCurrentSize()
{
synchronized(lockObject) {
currentSize--;
}
}
public static void main(String args[]){
Thread t = new Thread(new Producerr());
Thread t1 = new Thread(new Consumerr());
t.start();
t1.start();
}
}
Consumerr.java
import java.lang.*;
class Consumerr implements Runnable {
public void wwait() {
while (ProdCom.isEmpty()){
System.out.println("inside consumer wait: ");
System.out.println("number of elements: " + ProdCom.getCurrentSize());
try {
/* we don't spinlock here */
Thread.sleep(50);
} catch (Exception e) {
/* do nothing */
}
}
}
public void signal(){
ProdCom.decCurrentSize();
}
public void run(){
do{
this.wwait();
ProdCom.acquire();
System.out.println("Num elements " + ProdCom.getCurrentSize());
System.out.println("Consuming!");
this.signal();
ProdCom.release();
} while (true);
}
}
Producerr.java
import java.lang.*;
class Producerr implements Runnable {
public void wwait(){
while (ProdCom.isFull()){
try {
Thread.sleep(50);
} catch(Exception e) { /* do nothing */ }
}
}
public void signal(){
ProdCom.incCurrentSize();
}
public void run(){
do {
this.wwait();
ProdCom.acquire();
System.out.println("Num elements : " + ProdCom.getCurrentSize());
System.out.println("producing!");
this.signal();
ProdCom.release();
} while (true);
}
}
The Java memory models allows threads to cache the values of variables, and different threads to have different caches. This means that the spin lock in acquire easily becomes an infinite loop: the thread in acquire may use the cached value mutx = 1 and never read the updated value from main memory:
while (mutx == 1); // infinite loop even if another thread changes mutx
Another problem is that the ++ and -- operators are not atomic: they read the value of the variable, modify it, and write it back. If two threads run currentSize++ and currentSize-- at the same time it is possible one of them is lost.
You can fix these problems by using an AtomicInteger object and its methods instead of int, for example in ProdCom:
static AtomicInteger currentSize = new AtomicInteger(0);
static AtomicInteger mutx = new AtomicInteger(0);
public static void acquire() {
while (!mutx.compareAndSet(0, 1));
}
public static void release() {
mutx.set(0);
}
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.
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).
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.
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