Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 1 year ago.
Improve this question
i have this code and i cant understand why main thread doesn't print false after 1sec ???
public abstract class Callable<E> implements Runnable {
private E val=null;
protected abstract E call();
public synchronized boolean isReady()
{
if(val!=null)
return true;
return false;
}
public synchronized E waitForValue() throws InterruptedException
{
while(!isReady())
{
wait();
}
return val;
}
public synchronized void run()
{
E temp = call();
val = temp;
notifyAll();
}
public static void main(String[] args) throws InterruptedException
{
Callable<String> c = new Callable<String>() {
protected String call() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
return "AAA";
}};
new Thread(c).start();
Thread.sleep(1000);
System.out.println(c.isReady());
System.out.println(c.waitForValue());
System.out.println(c.isReady());
}
}
if i change synchronized of method run like that it works
#Override
public void run() {
E temp = call();
synchronized (this) {
val = temp;
isReady = true;
notifyAll();
}
}
if thread sleep it doesn't release the lock of the object ?
and about wait it release the lock right ?
in the last i should print
false //after 1sec
AAA //after 4sec
true
The documentation can answer questions like this, and usually does.
Thread.sleep() does not release the monitor (or 'lock').
Object.wait() does release the monitor.
Related
This question already has answers here:
How I can replace deprecated method this.stop() in ThreadGroup
(2 answers)
Closed 3 years ago.
I am working on java version upgrade project and I am on the work where I need to replace deprecated methods.
this.stop();
Code USed this method are in ::
ThreadedTestGroup.java::
package utmj.threaded;
import junit.framework.*;
public class ThreadedTestGroup extends ThreadGroup {
private Test test;
private TestResult testResult;
public ThreadedTestGroup(Test test) {
super("ThreadedTestGroup");
this.test = test;
}
public void interruptThenStop() {
this.interrupt();
if (this.activeCount() > 0) {
this.stop(); // For those threads which won't interrupt
}
}
public void setTestResult(TestResult result) {
testResult = result;
}
public void uncaughtException(Thread t, Throwable e) {
if (e instanceof ThreadDeath) {
return;
}
if (e instanceof AssertionFailedError) {
testResult.addFailure(test, (AssertionFailedError) e);
} else {
testResult.addError(test, e);
}
this.interruptThenStop();
}
}
ConcurrentTestCase.java
package utmj.threaded;
import java.util.*;
import junit.framework.*;
/
public class ConcurrentTestCase extends TestCase {
private TestResult currentResult;
private ThreadedTestGroup threadGroup;
private Hashtable threads = new Hashtable();
private boolean deadlockDetected = false;
private Vector checkpoints = new Vector();
class ConcurrentTestThread extends Thread {
private volatile boolean hasStarted = false;
private volatile boolean hasFinished = false;
ConcurrentTestThread(
ThreadGroup group,
Runnable runnable,
String name) {
super(group, runnable, name);
}
public void run() {
hasStarted = true;
super.run();
finishThread(this);
}
}
public ConcurrentTestCase(String name) {
super(name);
}
public ConcurrentTestCase() {
super();
}
protected void addThread(String name, final Runnable runnable) {
if (threads.get(name) != null) {
fail("Thread with name '" + name + "' already exists");
}
ConcurrentTestThread newThread =
new ConcurrentTestThread(threadGroup, runnable, name);
threads.put(name, newThread);
}
public synchronized void checkpoint(String checkpointName) {
checkpoints.addElement(checkpointName);
this.notifyAll();
}
public boolean checkpointReached(String checkpointName) {
return checkpoints.contains(checkpointName);
}
public boolean deadlockDetected() {
return deadlockDetected;
}
private synchronized void finishThread(ConcurrentTestThread thread) {
thread.hasFinished = true;
this.notifyAll();
}
private ConcurrentTestThread getThread(String threadName) {
return (ConcurrentTestThread) threads.get(threadName);
}
/**
* Returns true if the thread finished normally, i.e. was not inerrupted or stopped
*/
public boolean hasThreadFinished(String threadName) {
ConcurrentTestThread thread = this.getThread(threadName);
if (thread == null) {
fail("Unknown Thread: " + threadName);
}
return thread.hasFinished;
}
public boolean hasThreadStarted(String threadName) {
ConcurrentTestThread thread = this.getThread(threadName);
if (thread == null) {
fail("Unknown Thread: " + threadName);
}
return thread.hasStarted;
}
private void interruptAllAliveThreads() {
threadGroup.interruptThenStop();
}
/**
* Wait till all threads have finished. Wait maximally millisecondsToWait.
* Should only be called after startThreads().
*/
protected void joinAllThreads(long millisecondsToWait) {
Enumeration enum1 = threads.elements();
long remainingMilliseconds = millisecondsToWait;
while (enum1.hasMoreElements()) {
long before = System.currentTimeMillis();
ConcurrentTestThread each =
(ConcurrentTestThread) enum1.nextElement();
try {
each.join(remainingMilliseconds);
} catch (InterruptedException ignored) {
}
long spent = System.currentTimeMillis() - before;
if (millisecondsToWait != 0) {
remainingMilliseconds = remainingMilliseconds - spent;
if (remainingMilliseconds <= 0) {
deadlockDetected = true;
break;
}
}
}
}
public void joinThread(String threadName) throws InterruptedException {
this.joinThread(threadName, 0);
}
public void joinThread(String threadName, long millisecondsToTimeout)
throws InterruptedException {
ConcurrentTestThread thread = this.getThread(threadName);
if (thread == null) {
fail("Unknown Thread: " + threadName);
}
thread.join(millisecondsToTimeout);
}
/**
* Stores the current result to be accessible during the test
*/
public void run(TestResult result) {
currentResult = result;
super.run(result);
}
protected void setUp() throws Exception {
threadGroup = new ThreadedTestGroup(this);
}
/**
* Sleep and ignore interruption
*/
public void sleep(long milliseconds) {
try {
Thread.sleep(milliseconds);
} catch (InterruptedException ignored) {
}
}
/**
* Run all threads and wait for them to finish without timeout
*/
protected void startAndJoinAllThreads() {
this.startAndJoinThreads(0);
}
protected void startThreads() {
threadGroup.setTestResult(currentResult);
Enumeration enum1 = threads.elements();
while (enum1.hasMoreElements()) {
ConcurrentTestThread each =
(ConcurrentTestThread) enum1.nextElement();
each.start();
each.hasStarted = true;
}
Thread.yield();
}
protected void tearDown() throws Exception {
this.interruptAllAliveThreads();
threads = new Hashtable();
checkpoints = new Vector();
deadlockDetected = false;
threadGroup = null;
currentResult = null;
}
public synchronized void waitForCheckpoint(String checkpointName) {
while (!this.checkpointReached(checkpointName)) {
try {
this.wait();
} catch (InterruptedException ignored) {
}
}
}
public synchronized void waitUntilFinished(String threadName) {
while (!this.hasThreadFinished(threadName)) {
try {
this.wait();
} catch (InterruptedException ignored) {
}
}
}
}
I tried to search lot about this but did not got suitable solution so is there anyone who can help me out to replace this.stop() method which is deprecated.
IDE message: The method stop() from the type ThreadGroup is deprecated
The javadoc is pretty clear about this:
Deprecated. This method is inherently unsafe. See Thread.stop() for details.
And in the javadoc for Thread, it goes on and on:
Deprecated. This method is inherently unsafe. Stopping a thread with Thread.stop causes it to unlock all of the monitors that it has locked (as a natural consequence of the unchecked ThreadDeath exception propagating up the stack). ...
The problem here: this is neither a new nor an "easy to solve" problem.
My recommendation how to approach this:
if you really care about this code base, then throw it away. Don't try to refactor something that was build on inherently bad ideas. Instead: evaluate your current requirements, and design something new that addresses them.
if you were told "we should fix deprecated stuff", then simply keep things as they are. But do spend some hours testing that existing code in your new setup. When things still work, then tell the person who made this request: "that reflection work would be really really expensive, but it seems things are still working. so let's just keep using it".
In other words: it might be possible to just do "minimal" changes to get rid of stop(), but changes are that you have to invest a lot of time. And you see, multi threaded code is really hard to get right, and even harder to properly test. Therefore it is hard to predict the cost of a "minimal refactoring", thus, as said: consider throwing it all away or keeping it as is.
This question already has answers here:
Java Wait and Notify: IllegalMonitorStateException
(2 answers)
Closed 4 years ago.
Was trying to practice producer and consumer using a simple counter in java.
Not sure why I am getting a Illegal Monitor State exception on this piece of code.
I have counter rest and counter consume methods which run in their own thread.
The counter itself is a static int volatile field .
The counter class also gives you a lock to
If I change the wait naotify to the following:
Counter.lock.notify();
Counter.lock.wait();
The code works. Dosen't wait() and notify() automatically takes the reference of the lock synchronize is on?
Producer Class
package multithreading;
public class CounterProducer implements Runnable {
public void run() {
try { incrCounter(); } catch (InterruptedException e) { e.printStackTrace(); }
}
public void incrCounter() throws InterruptedException {
while (true) {
synchronized (Counter.lock) {
if (Counter.counter < 1) {
System.out.println("Counter Reset");
Counter.counter = 10;
notify();
wait();
}
}
}
}
}
Consumer Class
package multithreading;
public class CounterConsumer implements Runnable {
public void run() {
try { consumeCounter(); } catch (InterruptedException e) { e.printStackTrace(); }
}
public void consumeCounter() throws InterruptedException {
while (true) {
synchronized (Counter.lock) {
if (Counter.counter > 0) {
System.out.println("Consumed");
Counter.counter--;
notify();
wait();
}
}
}
}
}
The Counter
public class Counter {
public static volatile int counter;
public static final Object lock = new Object();
}
The Counter
public class CounterRunner {
public static void main(String[] args) {
Thread con = new Thread(new CounterConsumer());
Thread prod = new Thread(new CounterProducer());
con.start();
prod.start();
}
}
The Runner
public class CounterRunner {
public static void main(String[] args) {
Thread con = new Thread(new CounterConsumer());
Thread prod = new Thread(new CounterProducer());
con.start();
prod.start();
}
}
If I change the wait naotify to the following, the code works:
Counter.lock.notify();
Counter.lock.wait();
Every Java method is either a static method of some class or an instance method of some object. If you see a method call that does not contain an explicit class name or object reference, then it is an implicit call to a method belonging to the this object.
That is to say, notify() means the same thing as this.notify(), and wait() means this.wait().
this, refers to the CounterProducer instance when it appears in your CounterProducer.incrCounter() method, and it refers to the CounterConsumer instance when it appears in your CounterConsumer.consumeCounter() method.
I have two threads. The first changes the value of variable Data. And second one print the value if its value has changed. I am trying to do that second thread just print each time that the variable's value changed, but I don't reach success. Someone can help me?
thread 1
class someservice{
volatile int data;
Boolean Flag = false;
public void mymethod(){
flag = true;
for (Integer i = 1; i < sheet.getRows(); i++) {
data = someMethod(); //this method when called return a new
//value
}
flag = false;
...
}
}
thread 2
Promise p = task {
try {
while (true) {
if (engineService.getFlag()) {
print(someservice.data);
}else{
break;
}
}
} catch(Throwable t) {
...
}
}
Since you mention Promises, I infer you are familiar with future/ promise in +C++11
in java there is a similar approach, with future callable...
public class HW5 {
public static void main(String[] argv) throws InterruptedException, ExecutionException {
FutureTask<Boolean> myFutureTask = new FutureTask<>(new Callable<Boolean>() {
#Override
public Boolean call() throws Exception {
// implement the logic here and return true if everything was
// ok, false otherwise.
Thread.sleep(5000);
System.out.println("dddd");
return System.currentTimeMillis() % 2 == 0;
}
});
ExecutorService executor = Executors.newFixedThreadPool(1);
executor.execute(myFutureTask);
Boolean result = myFutureTask.get();
System.out.println("Done!");
}
}
FutureTask in a class that takes a callable which can return an Object after its job is done... in Order to execute the Future task you can use a Executor service, especifically calling the method execute, since you need to wait for the thread to do the job then is necessary that you call Future.get, that will basically blocks the main thread until the future is done, to verify the result, just read the variable result..
You could use the notify() and notifyAll() methods within thread. Check out this link: https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html
public synchronized void guardedJoy() {
// This guard only loops once for each special event, which may not
// be the event we're waiting for.
while(!joy) {
try {
wait();
} catch (InterruptedException e) {}
}
System.out.println("Joy and efficiency have been achieved!");
}
public synchronized notifyJoy() {
joy = true;
notifyAll();
}
You have to look up more data about Concurrent programming,I can tell you now some basics,well,not so so basic,but i will do my best:
Here,you have a Monitor,it is an abstract concept,in resume,a Monitor is a
class with all it's
method using"syncronized"
as modifier, it means,
that only
one thread
can access
the method
at once.So,
in the
monitor is
the variable
that you
want to print,
and the"flag",
that tells you if
the variable
was modified.Finally,
you can
see the
most important thing,the"wait()"and"notify()"methods,
those method
stops the thread,or"play"
them again.
You ask
here in
the printValue() method, if your variable was changed, if the variable was'nt change, put the thead to sleep with the wait() method, and when the other
method changeValue() is executed, the value is modified, and the notify() method is called, waking up the thread, so, doing all this, you can guarantee three things:
Safety: meaning that the threads will do that you want
Absence of deadlock: meaning that the thread that is put to sleep, will be awake in the future.
Mutex: meaning that only one thread is executing the critical code, for example, the op. "++" is not atomic, is Subdivided inside in more the one action, create a local var, read the var, sum, and asign, so, if more than one thread are in the game, the value may not be consecutive, example:
i = 0;
i ++;
output: 1;
output: 2;
output: 3;
output: 5;
output: 4;
output: 7;
That could happen, and even so, that will happen in the next code, because there a more than one thread executing. Well, this is the way to program with several threads, more or less
public class Monitor {
private int value = 0;
public static boolean valueHasChanged = false;
public synchronized int changeValue(int newValue){
this.value = newValue;
Monitor.valueHasChanged = true;
this.notify();
return this.value + 1;
}
public synchronized void printValue(){
while(!Monitor.valueHasChanged){
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(this.value);
Monitor.valueHasChanged = false;
}
public static void main(String[] args) {
Monitor ac = new Monitor();
BClass t1 = new BClass(ac);
AClass t2 = new AClass(ac);
t1.start();
t2.start();
}
public int getValue() {
return this.value;
}
}
Now the threads:
public class AClass extends Thread{
private Monitor ac;
public AClass(Monitor ac) {
this.ac = ac;
}
#Override
public void run() {
while(true){
this.ac.printValue();
}
}
}
And finally:
public class BClass extends Thread{
private Monitor ac;
public BClass(Monitor ac) {
this.ac = ac;
}
#Override
public void run() {
int v = 0;
while(true){
this.ac.changeValue(v);
v++; // this sum is not secure, if you want to print an
// ascending order, the code is diferent, I will show in
// above.
}
}
Now, if you want an ordered print:
the monitor will look like:
public class Monitor {
private int value = 0;
public boolean valueHasChanged = false;
private boolean hasPrint = true;
public synchronized void changeValue(int newValue) {
this.value = newValue;
this.valueHasChanged = true;
this.notify();
}
public synchronized void changeValuePlusOne() {
while (!hasPrint) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.value++;
this.valueHasChanged = true;
this.hasPrint = false;
this.notifyAll();
}
public synchronized void printValue() {
while (!this.valueHasChanged) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(this.value);
this.valueHasChanged = false;
this.hasPrint = true;
this.notifyAll();
}
public static void main(String[] args) {
Monitor ac = new Monitor();
BClass t1 = new BClass(ac);
AClass t2 = new AClass(ac);
t1.start();
t2.start();
}
public int getValue() {
return this.value;
}
}
And the Threads:
public class BClass extends Thread{
private Monitor ac;
public BClass(Monitor ac) {
this.ac = ac;
}
#Override
public void run() {
while(true){
this.ac.changeValuePlusOne();
}
}
}
The other Thread look equals:
public class AClass extends Thread{
private Monitor ac;
public AClass(Monitor ac) {
this.ac = ac;
}
#Override
public void run() {
while(true){
this.ac.printValue();
}
}
}
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I have the following use case. Can anyone suggest a good implementation of method t1() assuming it would be run on JAVA 6 ? I tried to think of accomplishing this using wait() and notify() but could not get a proper solution. Any help will be appreciated. (Note that both of these methods t1() and m1() will be called in different threads)
class Test
{
static volatile int flag = 0;
public static void t1()
{
//This method will be called in a Thread called T2
/*This method must wait for flag to become 1. As soon it
becomes 1 this must return. However it should wait for maximum
n seconds. After that even if flag is 0 it must return.*/
}
public static void m1()
{
//This method will be called in a Thread called T1
flag = 1;
}
}
This is what I tried so far as implementation of t1()
public static void t1() throws InterruptedException
{
while(flag == 0)
{
Thread.currentThread().sleep(100);
}
}
Above works but problem is timeout is not implemented and while loop does not seem to be that good.
Use a CountDownLatch. Initialize it before any of the threads run with the count to one. Your code will then look something like this:
class Test
{
static CountDownLatch latch = new CountDownLatch(1);
public static void t1()
{
//This method will be called in a Thread called T2
/*This method must wait for flag to become 1. As soon it
becomes 1 this must return. However it should wait for maximum
n seconds. After that even if flag is 0 it must return.*/
latch.await(1L,TimeUnit.SECONDS);
//your remaining logic
}
public static void m1()
{
//your logic
latch.countDown();
}
}
A CountDownLatch is a somewhat modified, enhanced (e.g. timeout option), and arguably easier-to-understand implementation of a Semaphore - one of the basic structures used widely for thread synchronization across a number of languages (not only Java). Note the following when comparing the Wikipedia reference to the Java implementation:
P/wait() corresponds to await(), with the difference that await() doesn't change the count value.
V/signal() corresponds to countDown(), with the difference that countDown() counts down, not up (obviously).
Use a CountDownLatch
private static CountDownLatch countDownLatch = new CountDownLatch(1);
public static void t1() throws InterruptedException {
countDownLatch.await(1000L, TimeUnit.MILLISECONDS);
System.out.println("t2");
}
public static void m1() throws InterruptedException {
System.out.println("t1");
// you can simulate some activity
Thread.sleep(500);
countDownLatch.countDown();
}
The thread running t1() will have to wait up to a second.
public static void main(String[] args) throws IOException, ParseException {
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
try {
test.Test.m1();
} catch (InterruptedException e) {
// do something
}
}
});
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
try {
test.Test.t1();
} catch (InterruptedException e) {
// do something
}
}
});
t2.start();
t1.start();
}
This is a bad idea in a static context though as other classes will have access to it and may call the methods, which will screw up the latch.
You could poll until the condition is satisfied. Instead of using Thread.sleep(long time) between checks, I suppose it's more practical to just use Thread.yield():
public static void t1()
{
while (flag == 0)
{
Thread.yield();
}
}
Narrative complete example using CountDownLatch
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class Race {
public static void main(String[] args) {
boolean flag=true; //set false to see other behavior
if (flag) {
startRace(5L, 2L);
} else {
startRace(2L, 5L);
}
}
private static void startRace(final long s1, final long s2) {
new Thread() {
#Override
public void run() {
Test.t1(s1);
}
}.start();
new Thread() {
#Override
public void run() {
Test.t2(s2);
}
}.start();
}
}
class Test {
static volatile int flag = 0;
static CountDownLatch L = new CountDownLatch(1);
public static void t1(long n) {
await(n);
logic1();
L.countDown(); // comment to wait till end
}
public static void t2(long n) {
await(n);
logic2();
L.countDown();
}
private static void logic1() {
if (flag == 0) {
System.out.println(Thread.currentThread()
+ ": Flag Couldnt be set in time");
} else {
System.out.println(Thread.currentThread() + ": Flag set in time");
}
}
private static void logic2() {
flag = 1;
System.out.println(Thread.currentThread() + ": Flag Set");
}
private static void await(long n) {
waitMsg(n);
try {
if (L.await(n, TimeUnit.SECONDS)) {
waitOverBefore(n);
} else {
waitOver(n);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private static void waitOverBefore(long n) {
System.out.println(Thread.currentThread() + ": Waiting Over before "
+ n + " seconds");
}
private static void waitOver(long n) {
System.out.println(Thread.currentThread() + ":" + n
+ " seconds Waiting Over");
}
private static void waitMsg(long n) {
System.out.println(Thread.currentThread() + ":Waiting for " + n
+ " seconds");
}
}
Output 1
Thread[Thread-0,5,main]:Waiting for 5 seconds
Thread[Thread-1,5,main]:Waiting for 2 seconds
Thread[Thread-1,5,main]:2 seconds Waiting Over
Thread[Thread-1,5,main]: Flag Set
Thread[Thread-0,5,main]: Waiting Over before 5 seconds
Thread[Thread-0,5,main]: Flag set in time
Output 2
Thread[Thread-1,5,main]:Waiting for 5 seconds
Thread[Thread-0,5,main]:Waiting for 2 seconds
Thread[Thread-0,5,main]:2 seconds Waiting Over
Thread[Thread-0,5,main]: Flag Couldnt be set in time
Thread[Thread-1,5,main]: Waiting Over before 5 seconds
Thread[Thread-1,5,main]: Flag Set
Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
I was trying to write a code where multiple threads call methods on a shared object to increment/decrement/print a counter stored in it. What I also want are these numbers to vascillate between 0 and 8. That is the output might look like something below:
0123234567654566677877666655....
Can somebody look at what I have cranked out and give me some pointers on whether I am on the right track:
My shared object:
public class SyncObj{
private int i;
public synchronized void inc(){
if(i<8)
i++;
}
public synchronized void dec(){
if(i > 0)
i--;
}
public synchronized void print(){
System.out.print(i);
}
}
To prevent starvation on the print and to make sure every inc/dec gets printed, I can have a private variable called hasPrinted and rewrite the class as follows:
public class SyncObj{
private int i;
//Changed Boolean to boolean as Keith Randall pointed out
private boolean hasPrinted = false;
public synchronized void inc(){
if(i<8 && hasPrinted){
i++;
hasPrinted = false;
}
}
public synchronized void dec(){
if(i > 0 && hasPrinted){
i--;
hasPrinted = false;
}
}
public synchronized void print(){
System.out.print(i);
hasPrinted = true;
}
}
Can somebody go over the above snippet and review it for pitfalls and gotchas?
Thanks
You should get used to using a queue for printing.
public class SyncObj {
private volatile int i;
private BlockingQueue<Integer> q = new LinkedBlockingQueue<Integer>();
public synchronized void inc() {
if (i < 8) {
i++;
q.add(i);
}
}
public synchronized void dec() {
if (i > 0) {
i--;
q.add(i);
}
}
public void print() {
for (Integer i = q.poll(); i != null; i = q.poll()) {
System.out.print(i);
}
}
private static volatile boolean stop = false;
public static void main(String[] args) throws InterruptedException {
final SyncObj o = new SyncObj();
new Thread(new Runnable() {
#Override
public void run() {
while (!stop) {
o.inc();
}
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
while (!stop) {
o.dec();
}
}
}).start();
new Thread(new Runnable() {
#Override
public void run() {
while (!stop) {
o.print();
}
}
}).start();
Thread.currentThread().sleep(1000);
stop = true;
}
}
My output looks like this:
1012345678765432101234567876543210123456787654321012345678765432101234567876543210123456787654321012345678
Boolean -> boolean, no point in having an object instead of a primitive type.
Your first code is fine. Your second code doesn't solve your requirements of preventing starvation or making sure every inc/dec gets printed. Why not just have inc/dec print the value itself?