Java unisex bathroom - java

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.

Related

Java lock conditions seem to not be working right

I have a problem where there is a BoundedBuffer and there are Consumers and Producers, the producers fill the buffer and consumers remove from the buffer.
I'm using threads for the Consumers and Producers, and i was trying to use lock conditions to ensure that the buffer isn't full to the producer and isn't empty for the consumer.
Unfortunately it's not working the way I wanted, it seems that the Consumer/Producer, when they are in Condition.await, don't let the other threads work. Shouldn't they let them?
Here is my code
class main
{
public static void main (String[] args) throws InterruptedException
{
final int N = Integer.parseInt(args[0]);
BoundedBuffer teste = new BoundedBuffer(N);
Thread c = new Consumidor(teste,N);
Thread p = new Produtor(teste,N);
c.start();
p.start();
c.join();
p.join();
}
}
class BoundedBuffer
{
ArrayList<Integer> array;
int index;
int size;
Lock l = new ReentrantLock();
Condition notFull = l.newCondition();
Condition notEmpty = l.newCondition();
BoundedBuffer(int N)
{
this.array=new ArrayList<Integer>(N);
this.index = 0;
this.size=N;
}
public synchronized void put(int e) throws InterruptedException
{
l.lock();
try
{
while(this.index >= this.size)
{
notFull.await();
}
this.array.add(index,e);
this.index++;
notEmpty.signal();
}
finally
{
l.unlock();
}
}
public synchronized int get() throws InterruptedException
{
int i;
l.lock();
try
{
while(this.index <=0)
{
notEmpty.await();
}
this.index--;
notFull.signal();
i = this.array.get(index);
}
finally
{
l.unlock();
}
return i;
}
}
class Consumidor extends Thread
{
private BoundedBuffer b;
final int j;
public Consumidor(BoundedBuffer b, int j)
{
this.b = b;
this.j=j;
}
public void run()
{
int a;
for (int i = 0; i < j ;++i)
{
try
{
a=b.get();
System.out.println("GET: " +a);
}
catch (Exception e) {}
}
}
}
class Produtor extends Thread
{
private BoundedBuffer b;
final int j;
public Produtor(BoundedBuffer b, int j)
{
this.b = b;
this.j=j;
}
public void run()
{
int a;
for (int i = 0; i < j; ++i)
{
try
{
b.put(i);
System.out.println("PUT: " +i);
}
catch (Exception e) {}
}
}
}
Thanks in advance
Don’t mix intrinsic locks (meaning synchronized) with reentrantLocks. This code is trying to acquire the intrinsic lock and then the reentrantlock.
Putting synchronized on an instance method requires the thread calling the method to acquire the intrinsic lock on the instance. ReentrantLock is a separate locking construct that does not use that keyword. Mixing the two mechanisms is unnecessary and can only cause trouble.
(Specifically the code is calling await on the condition object, which causes the thread to release the reentrant lock, but the thread keeps holding onto the intrinsic lock, preventing the other thread from entering a synchronized method.)
The fix for this is to delete the synchronized keyword from your code.

synchronized keyword does not work as expected in java [duplicate]

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.

Puzzle about two workers and a cart. Usage lock and conditions doesn't work

When using synchronized block or method, we synchronized by mutable object. But I don't understand how to use Locks with Conditions from j.u.c.. I'm trying to solve puzzle with two workers and a cart with lock and conditions. When first worker add weight to the cart - second wait. When cart is full, than first worker wait and second releases the cart.
I create two threads for each worker and use one cart. But in reality only one thread performs (worker, that add weight) until cart is full. Than program blocks. What I'm doing wrong and what I misunderstand?
That's my implementation of this puzzle.
package puzzles.workers;
public enum WorkerType {
ADDER, REDUCER;
}
Cart class
package puzzles.workers;
public class Cart {
private static final int INITIAL_CAPACITY = 10;
private static final int INITIAL_WEIGHT = 0;
private int capacity;
private int weight;
public Cart() {
this(INITIAL_CAPACITY);
}
public Cart(int capacity) {
this.capacity = capacity;
weight = INITIAL_WEIGHT;
}
public void addWeight() {
weight++;
}
public void reduceWeight() {
weight--;
}
public int getCapacity() {
return capacity;
}
public int getWeight() {
return weight;
}
}
Worker class.
package puzzles.workers;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class WorkerWithLock implements Runnable {
private final Cart cart;
private WorkerType workerType;
final Lock lock = new ReentrantLock();
final Condition whenEmpty = lock.newCondition();
final Condition whenFull = lock.newCondition();
public WorkerWithLock(Cart cart, WorkerType workerType) {
this.cart = cart;
this.workerType = workerType;
}
#Override
public void run() {
while (true) {
if (workerType == WorkerType.ADDER) {
try {
addWeight();
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
} else {
try {
reduceWeight();
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
}
}
}
public void addWeight() throws InterruptedException {
lock.lock();
try {
while (cart.getWeight() == (cart.getCapacity() - 1)) {
whenFull.await();
}
cart.addWeight();
System.out.println("++ weight is: " + cart.getWeight());
whenEmpty.signalAll();
Thread.sleep(500);
} finally {
lock.unlock();
}
}
public void reduceWeight() throws InterruptedException {
lock.lock();
try {
while (cart.getWeight() == 0) {
whenEmpty.await();
}
cart.reduceWeight();
System.out.println("-- weight is: " + cart.getWeight());
whenFull.signalAll();
Thread.sleep(500);
} finally {
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
Cart cart = new Cart(5);
WorkerWithLock adder = new WorkerWithLock(cart, WorkerType.ADDER);
WorkerWithLock reducer = new WorkerWithLock(cart, WorkerType.REDUCER);
new Thread(reducer).start();
new Thread(adder).start();
}
}
It is a kind of a race condition
That is because both threads are waiting.
One in addWeightand one in reduceWeight.
First the reducer stops, if weight is 0. At this time, the adder is may be not already started.
Than the adder stops, if weight = cpacity - 1
Now, both are waiting for an interrupt().
EDIT1. See my comments in the code
public void addWeight() throws InterruptedException {
lock.lock();
try {
while (cart.getWeight() == (cart.getCapacity() - 1)) {
whenFull.await(); //<-- ADDER waits here
}
cart.addWeight();
System.out.println("++ weight is: " + cart.getWeight());
whenEmpty.signalAll(); //<-- Never called since both are waiting
Thread.sleep(500);
} finally {
lock.unlock();
}
}
public void reduceWeight() throws InterruptedException {
lock.lock();
try {
while (cart.getWeight() == 0) {
whenEmpty.await(); //<-- REDUCER waits here
}
cart.reduceWeight();
System.out.println("-- weight is: " + cart.getWeight());
whenFull.signalAll(); //<-- Never called since both are waiting
Thread.sleep(500);
} finally {
lock.unlock();
}
}
EDIT2: Ok, now I understand the behaviour.
Your code is designed to synchronize ONE object for multiple threads, but your are using TWO objects.
Every of your both WorkerWithLock Objects has its own Lock and Condition objects. So calls of lock.lock() and whenFull.signalAll() in object ADDER does not effect Object REDUCER.
Your code will work if you make the lock and condition variables static, so that both objects are working with the same lock and the same condition
final static Lock lock = new ReentrantLock();
final static Condition whenEmpty = lock.newCondition();
final static Condition whenFull = lock.newCondition();
Sometimes multithreading is hard :)

multithreading java xync

I'm new to multithreading. I need to calculate integral by partial sums using multiple threads. I want to find out if all threads finished calculating to show general sum, I'm doing it using sleep(500) but it's stupid. How can i do it by the right way?
public class MainClass {
private static int threadCount=10;
public static double generalSum=0;
private static ArrayList<CalculatingThread> threads;
public static void main(String[] args){
Calculator.setA(0);
Calculator.setB(2);
Calculator.setN(500);
threads=new ArrayList<CalculatingThread>();
int div=500/threadCount;
for (int i=0; i<div;i++){
CalculatingThread thread=new CalculatingThread();
thread.setJK(i*10,(i+1)*10-1);
thread.start();
threads.add(thread);
}
try {
Thread.currentThread().sleep(500);
System.out.println(generalSum);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class CalculatingThread extends Thread {
private int j;
private int k;
#Override
public void run(){
System.out.println("Partial sum: " + Calculator.calcIntegral(j, k));
Calculator.addToSumm(Calculator.calcIntegral(j, k));
//this.notify();
}
public void setJK(int j,int k) {
this.j = j;
this.k=k;
}
}
public class Calculator {
private static double a;
private static double b;
private static int n;
private static double InFunction(double x){
return Math.sin(x);
}
private double sum=0;
public static void setA(double a) {
Calculator.a = a;
}
public static void setB(double b) {
Calculator.b = b;
}
public static void setN(int n) {
Calculator.n = n;
}
public static double calcIntegral(int j,int k)
{
double result, h;
int i;
h = (b-a)/n; //Шаг сетки
result = 0;
for(i=j; i <= k; i++)
{
result += InFunction(a + h * i - h/2); //Вычисляем в средней точке и добавляем в сумму
}
result *= h;
return result;
}
public static synchronized void addToSumm(double sum){
MainClass.generalSum+=sum;
}
}
P.S. sorry, i know code is stupid, i will refactor it later
Replace
Thread.currentThread().sleep(500);
with
for (Thread thread : threads) {
thread.join();
}
This will make main thread to wait until all the created threads get completed. Also you can refer wait until all threads finish their work in java
you can use join to make the main thread wait for the others:
The join method allows one thread to wait for the completion of
another. If t is a Thread object whose thread is currently executing,
t.join(); causes the current thread to pause execution until t's
thread terminates. Overloads of join allow the programmer to specify a
waiting period. However, as with sleep, join is dependent on the OS
for timing, so you should not assume that join will wait exactly as
long as you specify.
save every thread you create in an array and then do join on them
so your main should look like
public class MainClass {
private static int threadCount=10;
public static double generalSum=0;
private static ArrayList<CalculatingThread> threads;
public static void main(String[] args){
Calculator.setA(0);
Calculator.setB(2);
Calculator.setN(500);
threads=new ArrayList<CalculatingThread>();
int div=500/threadCount;
for (int i=0; i<div;i++){
CalculatingThread thread=new CalculatingThread();
thread.setJK(i*10,(i+1)*10-1);
thread.start();
threads.add(thread);
}
try {
for (Thread curr: threads) {
curr.join();
}
System.out.println(generalSum);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
now on a side note, no series program is using sleep when it wants to wait. sleep is only used when you actually need a delay in a background thread
P.S.
do not refactor the code. it is excellent to post it like that, so i can see every mistake you do if u do. a lot better then most people posting only 1 line and then there is nothing i can do but ask for more details

Why not 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.

Categories

Resources