Java multi-thread - java

I'm a novice java programmer and kind of confused by the following code snippet. Does it mean the first thread coming in will share the lock with the third one? Hope someone could help me clarify. Thanks in advance.
public class T_6 extends Thread {
static Object o = new Object();
static int counter = 0;
int id;
public T_6(int id) {
this.id = id;
}
public void run () {
if ( counter++ == 1 ) //confused in here.
o = new Object();
synchronized ( o ) {
System.err.println( id + " --->" );
try {
sleep(1000);
} catch ( InterruptedException e ) {
System.err.println("Interrupted!");
}
System.err.println( id + " <---" );
}
}
public static void main (String args []) {
new T_6(1).start();
new T_6(2).start();
new T_6(3).start();
}
}

When you reach the up-count and if, you do a typical check-then-act operation. The problem here is that several threads can come here at the same time. This will mean they will have local copies of the counter. The different threads may all have a 0 local copy - meaning they will count up to 1 and create new objects - all of them. But they are stored in a static container - of which they may or may not have local copies. In short, whatever happens here is accidental. They may end up synchronizing over the same object - but they may try to synchronize over different objects, meaning they won't synchronize at all.
You should have a look at the final and volatile keywords.
final means a reference can't be repointed once pointed somewhere. This is a good idea for locks. If you change your declaration to
final static Object o = new Object();
you are guaranteed that o cannot change, and all synchronizations will be over the same object.
volatile means it is forbidden for the VM to store a thread-local copy of a variable. All reads and writes must be to memory. This means that all threads will see writes that other threads do.

To ensure proper synchronization between multiple threads, all must acquire lock on the same object, or else synchronization will not be achieved.
Take a look at this part of your code:
if ( counter++ == 1 ) //confused in here.
o = new Object();
This part is not necessary at all to make the code thread-safe. Remove the above code which is causing confusion. You have already created instance of the object while declaring it. Now to ensure thread-safety between all the threads, make them acquire lock on the same object which you have already created.
Look here : static final Object o = new Object();
Just make the object final, to ensure you do not assign new value anywhere else in the code mistakenly/intentionally. You can directly use this object in synchronized fashion to ensure thread safety.

Does it mean the first thread coming in will share the lock with the
third one?
Yes, moreover, due to:
non-volatile static int counter = 0 variable
non-atomic operation ++
each thread will have its own copy of variable counter. It means that the following condition never true:
if ( counter++ == 1 )
o = new Object();
That's why all of these threads will share the same lock on object o initialized when declaring o.

Related

How to solve race condition of two writers using immutable objects

I was thinking about how to solve race condition between two threads which tries to write to the same variable using immutable objects and without helping any keywords such as synchronize(lock)/volatile in java.
But I couldn't figure it out, is it possible to solve this problem with such solution at all?
public class Test {
private static IAmSoImmutable iAmSoImmutable;
private static final Runnable increment1000Times = () -> {
for (int i = 0; i < 1000; i++) {
iAmSoImmutable.increment();
}
};
public static void main(String... args) throws Exception {
for (int i = 0; i < 10; i++) {
iAmSoImmutable = new IAmSoImmutable(0);
Thread t1 = new Thread(increment1000Times);
Thread t2 = new Thread(increment1000Times);
t1.start();
t2.start();
t1.join();
t2.join();
// Prints a different result every time -- why? :
System.out.println(iAmSoImmutable.value);
}
}
public static class IAmSoImmutable {
private int value;
public IAmSoImmutable(int value) {
this.value = value;
}
public IAmSoImmutable increment() {
return new IAmSoImmutable(++value);
}
}
If you run this code you'll get different answers every time, which mean a race condition is happening.
You can not solve race condition without using any of existence synchronisation (or volatile) techniques. That what they were designed for. If it would be possible there would be no need of them.
More particularly your code seems to be broken. This method:
public IAmSoImmutable increment() {
return new IAmSoImmutable(++value);
}
is nonsense for two reasons:
1) It makes broken immutability of class, because it changes object's variable value.
2) Its result - new instance of class IAmSoImmutable - is never used.
The fundamental problem here is that you've misunderstood what "immutability" means.
"Immutability" means — no writes. Values are created, but are never modified.
Immutability ensures that there are no race conditions, because race conditions are always caused by writes: either two threads performing writes that aren't consistent with each other, or one thread performing writes and another thread performing reads that give inconsistent results, or similar.
(Caveat: even an immutable object is effectively mutable during construction — Java creates the object, then populates its fields — so in addition to being immutable in general, you need to use the final keyword appropriately and take care with what you do in the constructor. But, those are minor details.)
With that understanding, we can go back to your initial sentence:
I was thinking about how to solve race condition between two threads which tries to write to the same variable using immutable objects and without helping any keywords such as synchronize(lock)/volatile in java.
The problem here is that you actually aren't using immutable objects: your entire goal is to perform writes, and the entire concept of immutability is that no writes happen. These are not compatible.
That said, immutability certainly has its place. You can have immutable IAmSoImmutable objects, with the only writes being that you swap these objects out for each other. That helps simplify the problem, by reducing the scope of writes that you have to worry about: there's only one kind of write. But even that one kind of write will require synchronization.
The best approach here is probably to use an AtomicReference<IAmSoImmutable>. This provides a non-blocking way to swap out your IAmSoImmutable-s, while guaranteeing that no write gets silently dropped.
(In fact, in the special case that your value is just an integer, the JDK provides AtomicInteger that handles the necessary compare-and-swap loops and so on for threadsafe incrementation.)
Even if the problems are resolved by :
Avoiding the change of IAmSoImmutable.value
Reassigning the new object created within increment() back into the iAmSoImmutable reference.
There still are pieces of your code that are not atomic and that needs a sort of synchronization.
A solution would be to use a synchronized method of course
public synchronized static void increment() {
iAmSoImmutable = iAmSoImmutable.increment();
}
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
increment();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
increment();
}
});

Java: synchronize object inside another synchronized object

I am trying to get familiar with wait() and notify() methods and I have written a simple class acting like a monitor for a simple producer-consumer excercise where there are N producers and N consumers. Anyway the monitor, as requested in the excercise, can store only 3 items. So the producers must wait; on the contrary if there are 0 items in the monitor the consumers must wait.
public class Monitor {
private List<Integer> items;
private int capacity;
private Object waitProducer;
private Object waitConsumer;
private int counter;
public Monitor() {
this.items = new ArrayList<Integer>();
this.capacity = 3;
this.waitProducer = new Object();
this.waitConsumer = new Object();
this.counter = 0;
}
public void produce() throws InterruptedException {
synchronized (this) {
if (this.items.size() == this.capacity) {
synchronized (this.waitProducer) {
System.out.println("Producer " + Thread.currentThread().getId() + " aspetta");
this.waitProducer.wait(); /***/
}
}
counter++;
System.out.println("Thread " + Thread.currentThread().getId()
+ " produces object " + counter);
this.items.add(counter);
synchronized (this.waitConsumer) {
this.waitConsumer.notify();
}
}
}
public void consume() throws InterruptedException {
synchronized (this) {
if (this.items.size() == 0) {
synchronized (this.waitConsumer) {
this.waitConsumer.wait(); /***/
}
}
System.out.println("Thread " + Thread.currentThread().getId()
+ " consume object " + this.items.get(0));
this.items.remove(0);
synchronized (this.waitProducer) {
this.waitProducer.notify();
}
}
}
}
I think that there is a problem in lines with /***/: infact when the wait() method is invoked then the thread releases the lock on waitProducer (or waitConsumer) but it does not on the Monitor object. That's why when the first produces (of the first consumer) calls wait() then the Monitor object is no more obtainable. Obvioudly the access to the Monitor object must be in mutual exclusion so that to update correctly the list and the counter. So, what is the correct way? Thanks
Only one thread can execute the code inside synchronized blocks at a time.
Also, one must gain an exclusive lock on an object (via synchronized(object)) when calling wait() on that object.
This means, the unlocking/unblocking/notify code must be accessible to other threads outside of original block which called wait(). Otherwise, execution will wait forever.
In your code no other thread can reach this.waitConsumer.notify(); while one thread waits on this.waitProducer.wait();. Because all of it is also enclosed in a synchronized(this) block, other threads will keep contesting for locking on this.
#james large What do you mean that two threads can be synchronized in the same block if they are synchronized on different objects?
Suppose you have a synchronized block that looks like this:
synchronized(obj) {
...body of synchronized block...
}
...whatever happens next...
When Java thread T executes that statement, it starts by evaluating the expression, obj. That expression must either return null, or it must return a reference to an object. If it's null, then a NullPointerException will be thrown. Otherwise, thread T will attempt to lock the object.
No two threads can ever lock the same object at the same time. If the object already was locked by some other thread, then thread T will be unable to proceed until the object is unlocked.
When thread T finally is able to lock the object, it will execute the body of the synchronized block, and then it will unlock the object and move on to whatever happens next.
The important concept here is the expression, obj. Suppose that thread T evaluates obj, gets a reference to object O, locks it, and enters the synchronized block. Then thread U comes along, evaluates obj, gets a different object, P. Thread U will lock object P, and will be able to enter the synchronized block while thread T still is in there at the same time.
So how can that happen?
When it's intended, it might look like this:
class MyClass {
private final Object lock = new Object();
void foobar() {
synchronized(lock) { ... }
}
}
If thread T and thread U are operating on different instances of MyClass, then each instance will have its own lock object. Usually, in this case, the body of the synchronized block will only operate on other instance variables of MyClass. Since the two threads are operating on different data, there is no harm in them both being in the same synchronized block at the same time.
The purpose of synchronization is not to keep two threads out of the same method at the same time: The purpose is to keep two threads from operating on the same data at the same time.
Sometimes a newbie programmer writes this:
static Integer count = new Integer(0);
...
synchronized(count) {
count += 1;
...operate on static data...
}
This is almost always a mistake. When thread T enters the block, it will synchronize on the Integer object that is referenced by the static variable count. But then the next thing it does is update count to refer to a different Integer object. Then along comes thread U. U synchronizes on the new count, and both threads are in the same block, operating on the same static data when they should not.

Confusion Regarding java threads on same/different objects

public class Computation extends Thread {
private int num;
private boolean isComplete;
public Computation(int nu) {
num = nu;
}
public void run() {
System.out.println("Thread Called is: " + Thread.currentThread().getName());
}
public static void main(String... args) {
Computation [] c = new Computation[4];
for (int i = 0; i < 3; i++) {
c[i] = new Computation(i);
c[i].start();
}
}
}
My Question is in main function we are creating every time a new Computation object on which the thread is being started then why we need to snchrnoized the run method? As we know for every different class object 'this' reference is different so we don't need to synchronize.
Also in another Example:
public class DiffObjSynchronized implements Runnable {
#Override
public void run() {
move(Thread.currentThread().getId());
}
public synchronized void move(long id) {
System.out.print(id + " ");
System.out.print(id + " ");
}
public static void main(String []args) {
DiffObjSynchronized a = new DiffObjSynchronized();
/**** output ****/
// 8 9 8 9
new Thread(a).start();
new Thread(new DiffObjSynchronized()).start();
}
}
Here is second example just like first we create a Thread on 2 different instances of class. Here we synchronize the move() method but by definition:
"two different objects can enter the synchronized method at the same time"
Please share your feedback?
If I understand you correctly, your question is: "Why is the move method synchronized?"
The answer is: it shouldn't be, for two reasons:
It doesn't access any fields, so there is nothing that could be corrupted by having many threads inside that method at once.
Each thread gets a different instance of the object, and thus a different lock. So the synchronized modifier makes no difference. Each thread can still enter its own instance's move method because they have separate locks.
You only need to synchronize when you have some data which is being shared between threads, and at least one thread is modifying that data.
Your threads are operating on different objects since you create a new instance for each thread. The intrinsic lock used by synchronized belongs to the instance. So the synchronized methods entered by your threads are guarded by different locks.
You need to understand how synchronization works.
Threads take a 'lock' on the object on which you are synchronizing when they enter the synchronized block. If you have a synchronized method then in that case the object becomes the 'this' instance. Now, no 2 threads can take a lock on the same object at the same time. object locks are mutex based in philosophy so only once thread can hold the mutex at a time. When the thread holding the lock exits the synchronized method or the block, it releases the mutex and thus the object lock becomes available to other threads to request lock on.
This link explains the concepts excellently. It has pictures about disassembled byte code which shows how threads take and leave locks and why 2 threads on 2 different object dont block each other.

I don't understand why immutable objects in java are inherrently always threadsafe

I'm reading the Effective Java book and on the chapter on minimizing mutability Item 15.
Maybe I'm having trouble understanding the concept of thread-safety since I'm not experienced much in concurrency. Could I get an example that illustrates how an immutable object is always thread-safe?
Thank you in advance!
Immutable objects are threadsafe because they cannot be modified.
It doesn't matter if a million threads access the same object at the same time, because none of the threads can mutate the object.
Thread safe means that changing said object doesn't have adverse effects on other threads that are using that object. Immutable objects cannot be changed. Hence, by design, immutable objects are thread safe because no change can happen to them to begin with.
Keep in mind, threads might share references. If you change which object the reference points to (not changing the object itself but reassigning the reference to another object all together with the = sign), then thread safety is jeopardized.
Say you have a counter:
class Counter {
private int counter = 0;
public void increment() {
counter++;
}
public int getCounter() {
return counter;
}
}
And say this is your main method:
public static void main(String[] args) {
final Counter counter = new Counter();
final CountDownLatch startLatch = new CountDownLatch(1);
final CountDownLatch endLatch = new CountDownLatch(4);
final Runnable r = () -> {
try {
startLatch.await();
} catch (final InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 100; i++) {
counter.increment();
if (counter.getCounter() % 10 == 0) {
System.out.println(counter.getCounter());
}
}
endLatch.countDown();
};
new Thread(r).start();
new Thread(r).start();
new Thread(r).start();
new Thread(r).start();
startLatch.countDown();
try {
endLatch.await();
} catch (final InterruptedException e) {
e.printStackTrace();
}
}
It's long, but basically all it does is create a single Counter, and then creates 4 threads that increment the counter a hundred times each, and prints the counter's value if the value is a multiple of 20. What output do you get?
20
40
60
80
100
141 // <-- Huh? Not a multiple of 20?
120 // <-- What's up with the order here?
180
220
240
160 // <-- This is way out of place...
280
300
260
200
320
340
360
380
// <-- missing 400?
Well that's a surprise. Wrong values, values out of place, etc...
The thing is that sharing objects with mutable state like Counter presents a lot of difficulties. You have to deal with locks, synchronization, etc. to get a mutable object to behave properly. In this case, synchronization is relatively easy, but making complicated objects synchronize right is hard. Take a look at the classes in java.util.concurrent if you want an example.
The nice thing about immutable objects is that they avoid this problem because they can't be modified. So no matter how many threads are doing something to an immutable object, you can be absolutely sure that it won't change, so you won't deal with strange results like this. An immutable Counter would be fairly useless, but something like a String that is immutable and can be shared across threads without worrying about synchronizing changes across threads is very useful in the concurrent world.
You can make a object immutable by removing all setters and any methods that change state of an object.
String is example of immutable object.
No matter how many threads access a String they cannot change it. Anytime you modify a String a new object is created.
So multiple threads can read the state but can never update the state.

Can I check for null on a shared field outside of a synchronized block in java?

Let's say I have a field that can be accessed by two separate threads. I'm using an Object for the synchronization lock. Can I check for null outside of the synchronization block? In other words, is this thread-safe:
private Object sharedObject() = new Object();
private final Object sharedObjectLock() = new Object();
private void awesomeMethod() {
if(sharedObject != null) {
synchronized(sharedObjectLock) {
//code the uses sharedObject
}
}
}
No. The assignment of the variable could occur after you check but before you get the lock.
There was, at one time, a school of thought that synchronized locks were expensive, but that's not true anymore. Just grab the lock.
No, it's not thread-safe. If another thread nullifies sharedObject field, your thread is not guaranteed to see that change.

Categories