Synchronized
In the multi threading environment when we want to restrict when only single thread can execute some piece of code at single instance of time other thread can keep waiting till the current executing thread finishes.
When Synchronization Not needed?
when you are only reading no updating the values.
or when dealing with the immutable objects
In case of immutable they shares the single copy from the memory itself not create the thread caches.
Two Basic Synchronization
1-synchronization block
For the method synchronization add the synchronized keyword in the method declarations
Another way to create synchronized code is with synchronized statements. Unlike synchronized methods, synchronized statements must specify the object that provides the intrinsic lock:
1- Class Level Locking - use of className.class
2- Object Level Locking - use of any object if none is used lock on this object is taken as granted
Both of the lock don't and Never Hinder the execution of one another
Some Points -
1-Note that constructors cannot be synchronized — using the
2-If you are taking lock on a NULL object will throws a NULL Pointer Exception
3-Synchronized block is better than synchronized method only take lock on the piece of code wherever needed
and also can take lock of your choice of object
4-From static block and methods you can never reference this so synchronized static block and synchronized method always provides class level lock.
5-It is not recommended to use String as a lock, because that string is present in the string pool and any other thread can also take the lock and result in the deadlock condition.
6-Java.util.concurrent.locks extends capability provided by java synchronized keyword for writing more sophisticated programs since they offer more capabilities e.g. Reentrancy and interruptible locks.
7-synchronized keyword is re-entrant in nature it means if a synchronized method calls another synchronized method which requires same lock then current thread which is holding lock can enter into that method without acquiring lock.
Ques
1- If a thread T1 enters a method m1 by obtaining the class level lock, does this mean another thread T2 cannot run a different method m2 by obtaining the object level lock?
No, it doesn't mean that. The "class level lock" is just a regular lock on a different object, namely SomeClass.class. The "object level lock" locks on this
2- can you create the object of the class while some thread has object or class level lock
yes since you are creating different object and you have lock on different object so it can be acheived.
public class Bar implements Runnable {
@Override
public void run() {
objectLock();
}
public void objectLock() {
System.out.println(Thread.currentThread().getName());
if (Thread.currentThread().getName().equals("t2")) {
Bar bb = new Bar();
System.out.println("Created BB and i am t2");
Class cc = Bar.class;
Constructor[] ccb = cc.getConstructors();
try {
Bar bn = (Bar) ccb[0].newInstance();
System.out.println("Again Cread and i am t2");
} catch (InstantiationException | IllegalAccessException
| IllegalArgumentException | InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
synchronized (Bar.class) {
try {
if (Thread.currentThread().getName().equals("t1"))
Thread.currentThread().sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("synchronized block "+ Thread.currentThread().getName());
System.out.println("synchronized block "+ Thread.currentThread().getName() + " end");
}
}
public static void main(String[] args) {
Bar b1 = new Bar();
Thread t1 = new Thread(b1);
Thread t2 = new Thread(b1);
Bar b2 = new Bar();
Thread t3 = new Thread(b2);
t1.setName("t1");
t2.setName("t2");
t3.setName("t3");
t1.start();
t2.start();
t3.start();
}
}
3- For the concurrent Read operation while lock, How will you achieve?
In the multi threading environment when we want to restrict when only single thread can execute some piece of code at single instance of time other thread can keep waiting till the current executing thread finishes.
When Synchronization Not needed?
when you are only reading no updating the values.
or when dealing with the immutable objects
In case of immutable they shares the single copy from the memory itself not create the thread caches.
Two Basic Synchronization
1-synchronization block
For the method synchronization add the synchronized keyword in the method declarations
public synchronized void increment() {
c++;
}
2-synchronization statementAnother way to create synchronized code is with synchronized statements. Unlike synchronized methods, synchronized statements must specify the object that provides the intrinsic lock:
synchronized(this) {
lastName = name;
nameCount++;
}
or
synchronized(Singleton.class)
{ if(_instance == null)
_instance = new Singleton();
}
Lock Type 1- Class Level Locking - use of className.class
2- Object Level Locking - use of any object if none is used lock on this object is taken as granted
Both of the lock don't and Never Hinder the execution of one another
Package java.util.concurrent.atomic -
Java.util.concurrent.atomic A small toolkit of classes that support lock-free thread-safe programming on single variables.
Instances of classes
AtomicBoolean, AtomicInteger, AtomicLong, and AtomicReference each provide access and updates to a single variable of the corresponding type. Each class also provides appropriate utility methods for that type. For example, classes AtomicLong and AtomicInteger provide atomic increment methods. One application is to generate sequence numbers, as in:class Sequencer {
private final AtomicLong sequenceNumber= new AtomicLong(0); public long next()
{ return sequenceNumber.getAndIncrement();
}
}
What is Difference between volatile and Atomic
private AtomicInteger counter = new AtomicInteger(); public int getNextUniqueIndex() { return counter.getAndIncrement(); }TheAtomicIntegerclass uses CAS (compare-and-swap) low-level CPU operations (no synchronization needed!) They allow you to modify particular variable only if the present value is equal to something else (and return it it succeed). So when you executegetAndIncrement()it actually runs in a loop (simplified real implementation):int current; do { current = get(); } while(!compareAndSet(current, current + 1));So basically: read; try to store incremented value; if not successful (the value is no longer equal tocurrent) read and try again. ThecompareAndSet()is implemented in native code (assembly).This cannot be achieve by volatile as we know Volatile only provides the visibilityso Pre and post increment of volatile may lead to the race condition, Pre and post increment is not atomic
rivate volatile int counter;
public int getNextUniqueIndex() {
return counter++;
}
This code is not correct. It fixes the visibility issue (
volatile makes sure other threads can see change made to counter) but still has a race condition. This has been explained multiple times: pre/post-incrementation is not atomic.
The only side effect of
volatile is "flushing" caches so that all other parties see the freshest version of the data. This is too strict in most situations; that's why volatile is not default.Some Points -
1-Note that constructors cannot be synchronized — using the
synchronized keyword with a constructor is a syntax error. Synchronizing constructors doesn't make sense, because only the thread that creates an object should have access to it while it is being constructed.2-If you are taking lock on a NULL object will throws a NULL Pointer Exception
3-Synchronized block is better than synchronized method only take lock on the piece of code wherever needed
and also can take lock of your choice of object
4-From static block and methods you can never reference this so synchronized static block and synchronized method always provides class level lock.
5-It is not recommended to use String as a lock, because that string is present in the string pool and any other thread can also take the lock and result in the deadlock condition.
6-Java.util.concurrent.locks extends capability provided by java synchronized keyword for writing more sophisticated programs since they offer more capabilities e.g. Reentrancy and interruptible locks.
7-synchronized keyword is re-entrant in nature it means if a synchronized method calls another synchronized method which requires same lock then current thread which is holding lock can enter into that method without acquiring lock.
Ques
1- If a thread T1 enters a method m1 by obtaining the class level lock, does this mean another thread T2 cannot run a different method m2 by obtaining the object level lock?
No, it doesn't mean that. The "class level lock" is just a regular lock on a different object, namely SomeClass.class. The "object level lock" locks on this
2- can you create the object of the class while some thread has object or class level lock
yes since you are creating different object and you have lock on different object so it can be acheived.
public class Bar implements Runnable {
@Override
public void run() {
objectLock();
}
public void objectLock() {
System.out.println(Thread.currentThread().getName());
if (Thread.currentThread().getName().equals("t2")) {
Bar bb = new Bar();
System.out.println("Created BB and i am t2");
Class cc = Bar.class;
Constructor[] ccb = cc.getConstructors();
try {
Bar bn = (Bar) ccb[0].newInstance();
System.out.println("Again Cread and i am t2");
} catch (InstantiationException | IllegalAccessException
| IllegalArgumentException | InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
synchronized (Bar.class) {
try {
if (Thread.currentThread().getName().equals("t1"))
Thread.currentThread().sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("synchronized block "+ Thread.currentThread().getName());
System.out.println("synchronized block "+ Thread.currentThread().getName() + " end");
}
}
public static void main(String[] args) {
Bar b1 = new Bar();
Thread t1 = new Thread(b1);
Thread t2 = new Thread(b1);
Bar b2 = new Bar();
Thread t3 = new Thread(b2);
t1.setName("t1");
t2.setName("t2");
t3.setName("t3");
t1.start();
t2.start();
t3.start();
}
}
3- For the concurrent Read operation while lock, How will you achieve?
stripping and using different locks for reading and writing.
A
java.util.concurrent.locks.ReadWriteLock is an advanced thread lock mechanism. It allows multiple threads to read a certain resource, but only one to write it, at a time.
Read Lock
If no threads have locked the ReadWriteLock for writing,
and no thread have requested a write lock (but not yet obtained it).
Thus, multiple threads can lock the lock for reading.
Write Lock
If no threads are reading or writing.
Thus, only one thread at a time can lock the lock for writing.
ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
readWriteLock.readLock().lock();
// multiple readers can enter this section
// if not locked for writing, and not writers waiting
// to lock for writing.
readWriteLock.readLock().unlock();
readWriteLock.writeLock().lock();
// only one writer can enter this section,
// and only if no threads are currently reading.
readWriteLock.writeLock().unlock();
Comments
Post a Comment