No deadlock while incrementing synchronized Integer objects - java

I am tried to implement deadlock in my program and all was ok except one issue which I can't explain.
public class Test {
public static void main(String[] args) throws InterruptedException {
Integer balanceA = 10000;
Integer balanceB = 10000;
Thread t1 = new Thread(() -> {
while (true) {
Processor.run(balanceA, balanceB);
}
});
Thread t2 = new Thread(() -> {
while (true) {
Processor.run(balanceB, balanceA);
}
});
t1.start();
t2.start();
t1.join();
t2.join();
}
}
class Processor {
public static void run(Integer balanceA, Integer balanceB) {
synchronized (balanceA) {
synchronized (balanceB) {
System.out.println(balanceA++ + "; " + balanceB--);
}
}
}
}
Why it always show me the same result as if I did't modify Integer values:
10000; 10000
10000; 10000
...

balanceA++ is equivalent to balanceA = balance + 1. It doesn't modify the Integer (it can't, because Integer is immutable). It just changes the value of the balanceA parameter to refer to a different object.
If you use AtomicInteger and call either incrementAndGet or getAndIncrement, then you'll see the values changing. You also won't need any synchronization.

Related

java thread synchronized & lock no effect?

so much confused why I get a random result while doing 'i++' in a synchronized or a locked method?
public class aaa implements Runnable {
static int count = 0;
public static void main(String[] args) {
aaa aaa = new aaa();
aaa.create();
}
public void create() {
ExecutorService executor = Executors.newFixedThreadPool(100);
for (int i = 0; i < 1000; i++) {
aaa thread = new aaa();
executor.execute(thread);
}
executor.shutdown();
while (true){
if(executor.isTerminated()){
System.out.println("a " + count);
break;
}
}
}
#Override
public void run() {
this.test();
}
public void test() {
Lock lock = new ReentrantLock();
try {
lock.lock();
count++;
System.out.println(count);
} finally {
lock.unlock();
}
}
}
OR:
public synchronized void test() {
count++;
System.out.println(count);
}
the result is a random number sometimes 1000 sometimes 998, 999 ...etc and the print from inside the 'test' method is not in a sequence, it is like :
867
836
825
824
821
820
819
817
816
a 999
However, if it is in a synchronized block, everything looks good:
public void test() {
synchronized (aaa.class) {
count++;
System.out.println(count);
}
}
the result:
993
994
995
996
997
998
999
1000
a 1000
I think all of the methods above should give me the same result 1000, and the self increment should be in a sequence, but only the last method works.What is wrong with the code? Please help!!!
You are creating multiple instances of aaa, each instance creates its own ReentrantLock, and every thread in execution smoothly acquires a lock from its own instance.
public void test() {
Lock lock = new ReentrantLock();
try {
lock.lock();
count++;
System.out.println(count);
} finally {
lock.unlock();
}
}
Since there are multiple instances of aaa, each thread is running on its own instance and the synchronized method uses current object of aaa.class
public synchronized void test() {
count++;
System.out.println(count);
}
The reason for getting a proper result in this approach is, you are using the aaa.class as an object to the synchronization
public void test() {
synchronized (aaa.class) {
count++;
System.out.println(count);
}
}
The solution is, reuse the same lock(ReentrantLock) across all the threads. Defining the lock in the same level as the variable count would solve the issue.
You must create a single mutex, i.e.
static Lock lock = new ReentrantLock();
Your synchronized method does not work since you are creating N aaa instances then, every (non static) method is different (with their own mutex).
Your synchronized (aaa.class) works since aaa.class is the same Object for all aaa instances and methods.
Then, if you need synchronize the method be sure it is the same for all threads, e.g. if test is static will be the same for all
#Override
public void run() {
test();
}
public static synchronized void test() {
count++;
}
but you can inject a "counter class", e.g.
class Counter {
int count = 0;
// non static but synchronized for all (since they use the same `counter` object)
synchronized void inc() {
count++;
}
}
to be used for all threads
...
SyncTest thread = new SyncTest(counter); // <== the same
...
(full code)
public class SyncTest implements Runnable {
private final Counter c;
public SyncTest(Counter c) {
this.c = c;
}
static class Counter {
int count = 0;
// non static but synchronized for all (since they use the same `counter` object)
synchronized void inc() {
count++;
}
}
#Override
public void run() {
test();
}
public void test() {
this.c.inc();
}
public static void main(String[] args) {
// one counter for all
Counter counter = new Counter();
ExecutorService executor = Executors.newFixedThreadPool(100);
for (int i = 0; i < 10000; i++) {
SyncTest thread = new SyncTest(counter);
executor.execute(thread);
}
executor.shutdown();
while (true) {
if (executor.isTerminated()) {
System.out.println("a " + counter.count);
break;
}
}
}
}
Rule of thumb: Declare your lock variable on the next line after the variable(s) that you want to protect with it, and declare it with the same keywords. E.g.,
public class aaa implements Runnable {
static int count = 0;
static Lock countLock = new ReentrantLock();
...
If you read deeply enough into any of the other answers here, then you will see why this helps.

Solving Counter Problem in Java Thread With synchronized method and block

I just wrote code for counter problem in a thread. When I add synchronized on Method its working fine but when I use synchronized block inside a method it does not work, why? Something I am missing, I guess.
public class CounterProblem {
class Counter implements Runnable {
private Integer count = 0;
#Override
public void run() {
for(int i = 0; i < 10000; i++) {
increment();
}
}
// THIS GIVES 20000 which is correct every time.
public synchronized void increment() {
count++;
}
// THIS GIVES wrong every time. WHY ?
// public void increment() {
// synchronized(count) {
// count++;
// }
// }
}
public static void main(String[] args) throws InterruptedException {
CounterProblem counterProblem = new CounterProblem();
Counter counter = counterProblem.new Counter();
Thread thread1 = new Thread(counter);
Thread thread2 = new Thread(counter);
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println(counter.count);
}
}
java.lang.Integer's aren't mutable. When you increment an Integer, you unbox it to a primitive int, increment it, and then autobox the result to a different Integer instance. This means your synchronized block synchronizes on a different object every time, making it pointless - as you've seen yourself.

Why volatile and synchronized statements cannot avoid thread interference here?

package simple;
public class ThreadInterference {
public static volatile Integer count = 1000;
public static class MyThread implements Runnable {
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 10000; i++) {
count++;
count--;
count++;
count--;
}
}
}
public static void main(String[] args) throws InterruptedException {
System.out.println(count);
Thread t1 = new Thread(new MyThread());
Thread t2 = new Thread(new MyThread());
Thread t3 = new Thread(new MyThread());
Thread t4 = new Thread(new MyThread());
t1.start();
t2.start();
t3.start();
t4.start();
t1.join();
t2.join();
t3.join();
t4.join();
System.out.println(count);
}
}
The count variable is marked as volatile but the output is:
1000
1230
If I change to synchronized statements, thread interference also happens:
package simple;
public class ThreadInterference {
public static Integer count = 1000;
public static class MyThread implements Runnable {
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 10000; i++) {
synchronized(count) {
count++;
count--;
count++;
count--;
}
}
}
}
public static void main(String[] args) throws InterruptedException {
System.out.println(count);
Thread t1 = new Thread(new MyThread());
Thread t2 = new Thread(new MyThread());
Thread t3 = new Thread(new MyThread());
Thread t4 = new Thread(new MyThread());
t1.start();
t2.start();
t3.start();
t4.start();
t1.join();
t2.join();
t3.join();
t4.join();
System.out.println(count);
}
}
output of this time is:
1000
1008
Why?
As others have noted, you have two separate problems. The first one is that count++ (and count--) isn't an atomic operation, even for primitive int types. So this won't work without some sort of locking or other concurrency handling. For count++ where count is an int, the compiler generates something like the following byte code instructions:
getstatic count
iconst_1
iadd
putstatic count
This is not likely to be atomic even if/when compiled to native code.
The second problem is that you are not locking on a consistent object, so operations are not serialised. The code:
count++; // "count" is an "Integer" object type.
Creates a new object. In essence it does something like the following:
count = Integer.valueOf(count.intValue() + 1);
So your count object is getting replaced by a new object, and subsequent entry into the synchronized section will be synchronizing against a different object.
As a safety tip, if you are using synchronized (someObject), where someObject is a class or instance field, then it's a good idea to make that field final. That way it can't be inadvertently reassigned to a different value.
There are two straightforward solutions to the problem that I can think of. One with locking against a specific object used for locking like so:
public class ThreadInterference {
public static final Object COUNT_LOCK = new Object();
public static int count = 1000; // Either "int" or "Integer" OK, depending on need
public static class MyThread implements Runnable {
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 10000; i++) {
synchronized(COUNT_LOCK) {
count++;
count--;
count++;
count--;
}
}
}
}
// And so on...
}
Another option is to use an AtomicInteger which may give better concurrent performance, if that matters:
public class ThreadInterference {
public static AtomicInteger count = new AtomicInteger(1000);
public static class MyThread implements Runnable {
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 10000; i++) {
count.incrementAndGet();
count.decrementAndGet();
count.incrementAndGet();
count.decrementAndGet();
}
}
}
// And so on...
}
I believe what is happening is this:
count++ tries to increment an Integer, which is immutable. The compiler must create a new Integer and refer to it as "count". Synchronization locks on the former count will then behave unexpectly. Somebody really smart could probably work it out...
Change count to a primitive int and synchronize on something else to see what happens. Or use an AtomicInteger.
Main takeaway is don't increment Integers! unless you are sure.
Instead of synchronizing count,
Try doing increment/decrement method that are themselves synchronized...
public static synchronized decrementCount()
{
count--;
}
public static synchronized incrementCount()
{
count++;
}
And call them instead of directly decrementing/incrementing.
Also, you should use atomic value if you are only doing a counter which prevent thread interference without resorting to synchronization.
Anyway, check this doc which show you how to do a synchronized counter with synchronized methods or atomic values : http://docs.oracle.com/javase/tutorial/essential/concurrency/atomicvars.html
When you are doing this, you are doing it wrong.
public static volatile Integer count = 1000;
for (int i = 0; i < 10000; i++) {
synchronized(count) {
count++;
count--;
count++;
count--;
}
}
Integer is immuttable. That means, when you are doing count++, it created a new Integer object, and assigned count with that new object. Meanwhile, synchronized part still reference the old object. So there exist a chance when every thread reached synchronized block with different object.
You should use variable that doesn't point to different object when the process happened.

Java Mutex implement

I'm implementing Mutex in Java, the code shown as below, I don't why the result doesn't match my expect,
as you can see in the result that I shown, it run as unpredictable
enum MutexStatus {
FREE, BUSY
};
enum FunctionTypes {
INCREASE, DECREASE
};
class Mutex {
private MutexStatus mutexStatus;
public Mutex() {
mutexStatus = MutexStatus.FREE;
}
public void acquire() {
synchronized (this) {
while (mutexStatus == MutexStatus.BUSY)
;
mutexStatus = MutexStatus.BUSY;
}
}
public void release() {
mutexStatus = MutexStatus.FREE;
}
}
class MyThread extends Thread {
private static Mutex mutex = new Mutex();
private static Integer sharedCounter = 0;
private FunctionTypes funcType;
public MyThread(String name, FunctionTypes functionType) {
super.setName(name);
funcType = functionType;
}
#Override
public void run() {
for (int i = 0; i < 100; i++) {
mutex.acquire();
switch (funcType) {
case INCREASE:
sharedCounter++;
System.out.println(Thread.currentThread().getName() + " -> "
+ sharedCounter);
break;
case DECREASE:
sharedCounter--;
System.out.println(Thread.currentThread().getName() + " -> "
+ sharedCounter);
break;
default:
break;
}
mutex.release();
}
}
}
public class MutexImplement {
public static void main(String[] args) {
// TODO Auto-generated method stub
MyThread IncreaseThread = new MyThread("Increase thread",
FunctionTypes.INCREASE);
IncreaseThread.start();
MyThread DecreaseThread = new MyThread("Decrease thread",
FunctionTypes.DECREASE);
DecreaseThread.start();
}
}
The result is
>Increase thread -> 1
>Decrease thread -> 0
>Increase thread -> 1
>Decrease thread -> 0
>Decrease thread -> 1
>Increase thread -> 1
>...........
Take a look at 17.4 in http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html. The threads will have their own local copy of the variables that they share (or don't actually). As already suggested make your shared variables volatile or use some synchronization/concurrency control. You may also want to take a look at the spin loop (the while loop) and use some signalling.
Now Java has lots of constructs to do this all for you though I suspect you have been asked to create a mutex yourself. For the record try to avoid your own homebrews and try and use the provided concurrency constructs.

Thread output inconsistent even when using synchronized keyword

I am very new to threads. I wrote a code and expected my output as 20000 consistently. But that's not the case. Please find the code below:
class Runner4 implements Runnable {
static int count = 0;
public synchronized void increase() {
count++;
}
#Override
public void run() {
for (int i = 0; i < 10000; i++) {
increase();
}
}
}
public class threading4 {
public static void main(String[] args) {
Thread t1 = new Thread(new Runner4());
t1.start();
Thread t2 = new Thread(new Runner4());
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Runner4.count);
}
}
Any explanation?
Thanks!!
You are synchronizing on two different objects in your code (corresponding to the two objects you created). As such, there is no protection of the shared static variable, and you get unpredictable results. Basically, there is no effective synchronization going on in your program. You can fix this with a simple modification.
Change:
public synchronized void increase(){
count++;
}
To:
public void increase(){
synchronized(Runner4.class) {
count++;
}
}
Note that I am not saying this is the best way to accomplish this kind of synchronization - but the important take-away is that, if you are modifying a class level variable, you need class level synchronization as well.
Your code would work if count was not static.
public synchronized void increase() {
// method body
}
is equivalent to
public void increase() {
synchronized(this) {
// method body
}
}
Since count is static, both t1 and t2 are accessing it with different locks, resulting in non-deterministic behavior. Either make Runner4.increase synchronize on a common lock (Runner4.class or a private static lock object would work just fine), or make count non-static.
The way you're trying to achieve what you want is is not really the best way.
A better way to do it is define a class called Counter, as the following:
public class Counter
{
int count;
public Counter()
{
count = 0;
}
public synchronized void increase() {
count++;
}
public int getCount()
{
return count;
}
}
The class has the methods of increasing the counter and getting it.
What you need to do now is have a Counter object to be shared by two threads that call the increase() method. So your thread class would look like this:
class Runner4 extends Thread {
Counter count;
public Runner4(Counter c)
{
count = c;
}
#Override
public void run() {
for (int i = 0; i < 10000; i++) {
count.increase();
}
}
}
Notice that the class takes a Counter object and calls the increase method. Also the class extends Thread instead of implementing Runnable. There is really no much difference, it's just now your Runner4 can use Thread class methods.
From your main defines a Counter object and two Runner4 threads, and then pass the Counter object to each one of them:
public static void main(String[] args) {
Counter count = new Counter();
Thread t1 = new Runner4(count);
t1.start();
Thread t2 = new Runner4(count);
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(count.getCount());
}

Categories

Resources