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.
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.
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.
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.
I have to solve this problem using Java semaphores, but I have no idea how, and I cannot find any related Java materials. This is how it goes:
There are to kinds of threads: men and women. Both wants to use same resources which quantity is BATHROOM_SIZE. 5 rules:
Every thread, after signaling need of using resource, should wait until he will be able to use it.
Prevent situation, when more than BATHOOM_SIZE threads is using resource concurrently.
Prevent woman and man use bathoom in the same time.
Threads should use resources concurrently. If there are many threads of one type, up to BATHROOM_SIZE threads should use resource.
Prevent starvation.
Results
Works for:
1woman, 1man, 5women, 5men
Fails for:
5women1men, 5men1women, 2men2women, 5men5women.
I've been trying to make it work since Monday and now I've run out of ideas.
Code
So my task is to write Bathroom.java class which implements BathroomInterface:
public interface BathroomInterface {
public static final int BATHROOM_SIZE = 3; //3 is just example
void manEnter();
void manExit();
void womanEnter();
void womanExit();
}
In system there are a number of man and woman threads which work like this:
for(int i = 0; i < n; i++) {
bathroom.manEnter();
//uses bathroom random amount of time
bathroom.manExit();
}
for(int i = 0; i < m; i++) {
bathroom.womanEnter();
//uses bathroom random amount of time
bathroom.womanExit();
}
I also have scheme of Bathroom.java class, I have to extend:
import java.util.concurrent.Semaphore;
public class Bathroom implements BathroomInterface {
private Semaphore mutex = new Semaphore(1, true);
public void womanEnter() {
mutex.acquireUninterruptibly();
}
public void womanExit() {
mutex.release();
}
public void manEnter() {
mutex.acquireUninterruptibly();
}
public void manExit() {
mutex.release();
}
}
This is what I made so far:
import java.util.concurrent.Semaphore;
public class Bathroom implements BathroomInterface {
int manW=0, manU=0, womanW=0, womanU=0; //*U-using, *W-waiting
private Semaphore mutex = new Semaphore(1, false);
public void womanEnter() {
womanW++;
StateChange();
}
public void womanExit() {
womanU--;
mutex.release();
StateChange();
}
public void manEnter(){
manW++;
StateChange();
}
public void manExit() {
manU--;
mutex.release();
StateChange();
}
void StateChange() {
if(womanU==0 && manU==0) {
if(manW>womanW) {
while(manW>0 && manU<BATHROOM_SIZE) {
manW--;
manU++;
mutex.acquireUninterruptibly();
}
}
else {
while(womanW>0 && womanU<BATHROOM_SIZE) {
womanW--;
womanU++;
mutex.acquireUninterruptibly();
}
}
}
if(womanU==0 && manU<BATHROOM_SIZE) {
while(manW>0 && manU<BATHROOM_SIZE) {
manW--;
manU++;
mutex.acquireUninterruptibly();
}
}
if(manU==0 && womanU<BATHROOM_SIZE) {
while(womanW>0 && womanU<BATHROOM_SIZE) {
womanW--;
womanU++;
mutex.acquireUninterruptibly();
}
}
}
}
Actually this exercise is done using a monitor, and not a semaphore. What you're doing is mostly fine, you're missing the conditions. So, in your bathroom class, declare:
a lock:
private Lock lock = new ReentrantLock();
2 conditions or queues, attached to your lock:
private Condition womenWaitingQueue = lock.newCondition();
private Condition menWaitingQueue = lock.newCondition();
2 counters to know how many are waiting, and 2 to know how many are using:
private int womenWaitingN = 0;
private int menWaitingN = 0;
private int womenUsingN = 0;
private int menUsingN = 0;
and of course, the number of resources:
private final int BATHROOM_CAPACITY = 5;
private int free_resources = BATHROOM_CAPACITY;
all 4 functions were here, but removed because of the homework tag
The important thing here is to prevent starvation, by not allowing any men to enter the bathroom if there are women waiting and viceversa.
so, conditions are that if a man wants to enter to the bathroom, it has to check if the bathroom has at least 1 free spot (using free resources) and if there are women in the bathroom (using womenUsingN). If any of these 2 conditions are not met, the man must wait(using the menWaitingQueue):
menWaitingQueue.await();
when a man leaves the bathroom, it has to check if there are any women waiting (womenWaitingN), if there are, they get notified:
womanWaitingQueue.signal();
because of the menUsingN counter, women signaled by this wont be able to enter until there are no men in the bathroom. If there are no women waiting, then a man can be signaled to enter the bathroom. This prevents starvation because priority is given to the opposite sex (if waiting).
The last thing, is that every function must lock/unlock the lock at beginning/end of each enter/exit function.
lock.lock();
lock.unlock();
I think with this new information you'll be able to make the functions on your own. Good luck!
I think you struggle with the whole mutex.acquire and mutex.release semantics, especially with what the mutex is actually supposed to guard. Let me try to simplify the problem a little to give you a hint as to how to approach this.
You are asked to implement a concurrency object that's more complicated than a simple semaphore, with two client classes and starvation prevention. I'm not going to do that for you, but i'm going to show you how a simple semaphore looked like in the pre-Java6 days:
public class Resource {
private int numClients = 0;
private final int maxClients;
public Resource(int maxClients) {
this.maxClients = maxClients;
}
public synchronized void acquire() {
while (!clientCanAcquire()) {
try {
wait();
} catch (InterruptedException e) {
}
}
++numClients;
printState();
}
public synchronized void release() {
--numClients;
printState();
notify();
}
private boolean clientCanAcquire() {
return numClients < maxClients;
}
private void printState() {
System.out.println("Resource is currently acquired by " + numClients
+ " clients");
}
}
A Client can access this as follows:
import java.util.Random;
public class Client implements Runnable {
private Resource resource;
private Random rnd = new Random();
public Client(Resource resource) {
this.resource = resource;
}
public void run() {
try {
Thread.sleep(rnd.nextInt(1000));
resource.acquire();
Thread.sleep(rnd.nextInt(1000));
resource.release();
} catch (InterruptedException e) {
}
}
}
and the simplest application that can drive the whole thing would look like this:
public class App {
public static void main(String[] arg) {
Resource r = new Resource(3);
for (int i = 0; i < 10; i++) {
Thread client = new Thread(new Client(r));
client.start();
}
}
}
Resource stores the information it needs to determine when a client can access in internal variables. In a multithreaded application, access to these variables must be synchronized. Shown here is the simplest way to do this, but you could also say
private Object mutex = new Object();
and then
synchronized (mutex) { }
or any other type of mutex.
Your problem is more complicated than a simple ordinary semaphore, but the underlying logic should be pretty similar.
#Th0rndike ok, i followed your hints and wrote sth like this:
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.*;
public class Bathroom implements BathroomInterface {
private Semaphore mutex = new Semaphore(1, false);
private Lock lock = new ReentrantLock();
private Condition womenWaitingQueue = lock.newCondition();
private Condition menWaitingQueue = lock.newCondition();
private int womenWaitingN = 0;
private int menWaitingN = 0;
private int womenUsingN = 0;
private int menUsingN = 0;
private int free_res = BATHROOM_SIZE;
public void womanEnter() {
lock.lock();
if(free_res>0 && menUsingN==0) {
womenUsingN++;
free_res--;
mutex.acquireUninterruptibly();
}
else
try {
womenWaitingQueue.await();
}
catch(Exception e) {
System.out.println("E!");
}
lock.unlock();
}
public void womanExit() {
lock.lock();
womenUsingN--;
free_res++;
mutex.release();
if(menWaitingN>0) {
try {
menWaitingQueue.signal();
}
catch(Exception e) {
System.out.println("E!");
}
}
lock.unlock();
}
public void manEnter() {
lock.lock();
menUsingN++;
free_res--;
if(free_res>0 && womenUsingN==0) {
mutex.acquireUninterruptibly();
}
else
try {
menWaitingQueue.await();
}
catch(Exception e) {
System.out.println("E!");
}
lock.unlock();
}
public void manExit() {
lock.lock();
menUsingN--;
free_res++;
mutex.release();
if(womenWaitingN>0) {
try {
womenWaitingQueue.signal();
}
catch(Exception e) {
System.out.println("E!");
}
}
lock.unlock();
}
}
But when I submit it to the automated program checker, in 1man and 1woman tests everything is ok, but in the rest, it returns "realtime exceeded" error. If I remove lock.lock()/unlock(), "realtime exceeded" errors will change to "wrong answer".
There is a solution at http://se.inf.ethz.ch/courses/2013a_spring/ccc/
You may refer that for some help.