In the sample code
public class MsLunch {
private long c1 = 0;
private long c2 = 0;
private Object lock1 = new Object();
private Object lock2 = new Object();
public void inc1() {
synchronized(lock1) {
c1++;
}
}
public void inc2() {
synchronized(lock2) {
c2++;
}
}
}
on this page,
lock1 and lock2 are controlling the updates on c1 and c2 resply.
However,
synchronized(lock2)
is acquiring the lock of the object lock1 and releasing it when the synchronized block
synchronized(lock1) {
c1++;
}
is executed.
While this block is being executed, there may be
an update on member c1 of this object still-- and I don't
see how this update is being prevented by
synchronizing on lock1 as in the code.
It is the object lock1 that there is exclusive access on--
and nothing else(?)
So, how is the implementation
public void inc1() {
synchronized(lock1) {
c1++;
}
}
in the above code different from
public void synchronized inc1() {
c1++;
}
or even
public void inc1() {
synchronized(c1) {
//do something on c1
}
}
when c1 is an object but not a primitive?
What am I missing here ?
Note: I saw
What is the difference between synchronized on lockObject and using this as the lock?
and
Java synchronized method lock on object, or method?
among some other discussions.
Implementation 1.
You are locking on the lock1 object. Nothing else that needs a lock on lock1 can execute. Having your two methods lock on different objects means that the two methods can run concurrently, but no two threads can run the same method concurrently.
Implementation 2.
Making a method synchronized means that the entire method body is implicitly in a synchronized(this) block (or synchronized on the Class object if the method is static. If both methods are synchronized, then one method would prevent the other from running at the same time, which is different then locking both methods on different objects.
Implementation 3.
If c1 is an object and not a primitive, then the semantics are very similar to implementation 1 - locking on an explicit object.
Marking a block or method synchronized without specifying a lock object synchronizes on the object who owns the method; in this case, the MsLunch instance. It's equivalent to synchronized(this). The purpose of the lock-object idiom is to break that lock up so that c1 and c2 can be manipulated separately. A synchronized block can only synchronize on an object, not a primitive.
synchronized(lock2){
// do sth
}
is actually acquiring lock of object lock2
where as
public void synchronized inc1() {
c1++;
}
acquires object on this object.
locks acquired by synchronized will be released once the program leaves the block.
Your statement is as far as I know incorrect. The page you linked doesn't state what you claim in your question neither. This is how locks work: Locks do not prevent threads of accessing an object at all. Locks only prevents another thread of acquiring the same lock while another thread already has acquired that lock.
This means that this can happen:
Thread A: synchronize (lockObject)
Thread B: lockObject.toString();
Thread A: release the lock on lockObject
This is what happens when two Threads want the same lock at the same time:
Thread A: synchronize (lockObject)
Thread B: synchronize (lockObject) // This will block until (1) !
Thread A: do some stuff and then release lock on lockObject
Thread B: gets the lock (1)
However:
public void synchronized inc1() {
c1++;
}
is exactly the same as:
public void inc1() {
synchronized(this) {
c1++;
}
}
I was having trouble with one thread hogging the lock
for(;;){synchronized(lockObject){
...
}}
I guess Java doesn't like to unlock it on its own the first chance it gets.
Using an java.util.concurrent.locks.ReentrantLock fixed the problem
static ReentrantLock lock = new ReentrantLock();
for(;;){
lock.lock();
...
lock.unlock();
}
Related
I've wrote some multithreading code in java and synchronized method that changed variable, but it doesn't synchronized my code, I still get random values. There is my code:
public class Main {
public static void main(String[] args) throws Exception {
Resource.i = 5;
MyThread myThread = new MyThread();
myThread.setName("one");
MyThread myThread2 = new MyThread();
myThread.start();
myThread2.start();
myThread.join();
myThread2.join();
System.out.println(Resource.i);
}
}
class MyThread extends Thread {
#Override
public void run() {
synMethod();
}
private synchronized void synMethod() {
int i = Resource.i;
if(Thread.currentThread().getName().equals("one")) {
Thread.yield();
}
i++;
Resource.i = i;
}
}
class Resource {
static int i;
}
Sometimes I get 7, sometimes 6, but I've synchronized synMethod, as I understand no thread should go at this method while some other thread executing this, so operations should be atomic, but they are not, and I can't understand why? Could you please explain it to me, and answer - how can I fix it?
Adding the synchronized method is like synchronizing on this. Since you have two different instances of threads, they don't lock each other out, and this synchronization doesn't really do anything.
In order for synchronization to take effect, you should synchronize on some shared resource. In your example, Resource.class could by a good choice:
private void synMethod() { // Not defined as synchronized
// Synchronization done here:
synchronized (Resource.class) {
int i = Resource.i;
if (Thread.currentThread().getName().equals("one")) {
Thread.yield();
}
i++;
Resource.i = i;
}
}
Let's have a look at definition of synchronized methods from oracle documentation page.
Making the methods synchronized has two effects:
First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
Coming back to your query:
synMethod() is a synchronized method object level. Two threads accessing same synchronized method acquire the object lock in sequential manner. But two threads accessing synchronized method of different instances (objects) run asynchronously in the absence of shared lock.
myThread and myThread2 are two different objects => The intrinsic locks are acquired in two different objects and hence you can access these methods asynchronously.
One solution : As quoted by Mureinik, use shared object for locking.
Other solution(s): Use better concurrency constructs like ReentrantLock etc.
You find few more alternatives in related SE question:
Avoid synchronized(this) in Java?
I am new to java learning the concepts of threading in java , i was planing to answer the following below questions
class Deadlocker
{
void executedByThreadOne();
void executedByThreadTwo();
}
Provide simple implementation of class Deadlocker above such that if the two methods are called concurrently by different threads, there will be chance of a deadlock.
folks please advise how such can we design class in java
Read some literature on deadlocks and think about, how to achieve this in a fake environment.
As a hint, you will propably need Thread.sleep to have your locks "overlapping". Imagine your locking process like an "x". Thread 1 is locking A, then sleeps, then locking B. But, while Thread 1 is sleeping, Thread B has to lock B and then try to lock A (which is already locked by A). Then you have your deadlock.
One source that can cause deadlock are locks. If you call method1 from one thread and method2 from the other, there will be a big chance of getting a deadlock:
Object lock1 = ...;
Object lock2 = ... ;
public void method1(){
synchronized (lock1) {
Thread.sleep(100);
synchronized (lock2) {
System.out.println("Acquired both locks");
}
}
}
public void method2(){
synchronized (lock2) {
Thread.sleep(100);
synchronized (lock1) {
System.out.println("Acquired both locks");
}
}
}
The above illustrates what is known as lock‐ordering deadlocks.
I've read this topic, and this blog article about try with resources locks, as the question popped in my head.
But actually, what I'd rather like would be a try with lock, I mean without lock instantiation. It would release us from the verbose
lock.lock();
try {
//Do some synchronized actions throwing Exception
} finally {
//unlock even if Exception is thrown
lock.unlock();
}
Would rather look like :
? implements Unlockable lock ;
...
try(lock) //implicitly calls lock.lock()
{
//Do some synchronized actions throwing Exception
} //implicitly calls finally{lock.unlock();}
So it would not be a TWR, but just some boilerplate cleaning.
Do you have any technical reasons to suggest describing why this would not be a reasonable idea?
EDIT : to clarify the difference between what I propose and a simple synchronized(lock){} block, check this snippet :
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class Test {
public static void main(String[] args) {
ReentrantLock locker =new ReentrantLock();
Condition condition = locker.newCondition();
Thread t1 = new Thread("Thread1") {
#Override
public void run(){
synchronized(locker){
try {
condition.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("Thread1 finished");
}
}
} ;
Thread t2 = new Thread("Thread2") {
#Override
public void run(){
synchronized(locker){
Thread.yield();
condition.signal();
System.out.println("blabla2");
}
}
} ;
t1.start();
t2.start();
}
}
Execution will result in a IllegalMonitorStateException, so lock() and unlock() methods are not implicitly called within synchronized block.
If you had to deal with a simple case like that, where the pattern of locking/unlocking was limited to a narrow scope like this, you probably don't want to use the more complicated Lock class and probably should just be using the synchronized keyword, instead. That being said, if for some reason you needed this with the more complicated Lock object, it should be relatively straight-forward to create a wrapper around Lock that implements the AutoCloseable interface to be able to do just that. Example:
class AutoUnlock implements AutoCloseable {
private final Lock lock;
public static AutoUnlock lock(Lock lock) {
lock.lock();
return new AutoUnlock(lock);
}
public static AutoUnlock tryLock(Lock lock) {
if (!lock.tryLock()) {
throw new LockNotAcquiredException();
}
return new AutoUnlock(lock);
}
#Override
public void close() {
lock.unlock();
}
private AutoUnlock(Lock lock) {
this.lock = lock;
}
}
With a wrapper like the above, you could then do:
try (AutoUnlock autoUnlock = AutoUnlock.lock(lock)) {
// ... do whatever that requires the lock ...
}
That being said, the Lock class is typically used for very complicated locking scenarios where this wouldn't be particularly useful. For example, Lock objects may be locked in one function in a class and later unlocked in another function (e.g. locking a row in a database in response to an incoming remote procedure call, and then unlocking that row in response to a later RPC), and thus having such a wrapper or making a Lock AutoCloseable, itself, would be of limited use for the way it is actually used. For more simple scenarios, it's more common to just use an existing concurrent datastructure or use synchronized.
This answer serves to explain the behavior of your edit. The purpose of synchronized is to lock the monitor of the given object when the thread enters the block (waiting if it isn't available) and releasing it when the thread exits the block.
Lock is a higher level abstraction.
Lock implementations provide more extensive locking operations than
can be obtained using synchronized methods and statements.
You can use it to lock across method boundaries. synchronized is not able to do this so a Lock cannot be implemented solely with synchronized and no implementation I've ever seen uses it. Instead, they use other patterns, like compare and swap. They use this to set a state atomically within a Lock object which marks a certain thread as the owner of the lock.
In your code snippet, you try to invoke
condition.signal();
in a thread which does not own the Lock from which the condition was created. The javadoc states
An implementation may (and typically does) require that the current
thread hold the lock associated with this Condition when this method
is called. Implementations must document this precondition and any
actions taken if the lock is not held. Typically, an exception such as
IllegalMonitorStateException will be thrown.
That's what happened here.
Executing
synchronized (lock) {}
makes the current thread lock (and then release) the monitor on the object referenced by lock. Executing
lock.lock();
makes the current thread set some state within the object referenced by lock which identifies it as the owner.
I am trying to learn threading, and regarding the following example
public class LockExample {
private Lock lockone = new ReentrantLock();
public void method1() {
lockone.lock();
try {
// do something
} finally {
lockone.unlock();
}
}
public void method2() {
lockone.lock();
try {
// do something
} finally {
lockone.unlock();
}
}
}
does it mean that if we lock method1 and method2 using the same lock, say thread A and B can not access method1 or method2at the same time. But if we lock method1 and method2using different locks lockone and locktwo, then threadA can access method1, at the same time thread Bcan access method2?
why don't we lock each method separately instead of putting them in one lock?
public class LockExample {
private Lock lockone = new ReentrantLock();
public void method1() {
lockone.lock();
try {
// do something
} // wrap the two methods in one lock?
}
public void method2() {
try {
// do something
} finally {
lockone.unlock();
}
}
}
}
does it mean that if we lock method1 and method2 using the same lock, say thread A and B can not access method1 or method2at the same time. But if we lock method1 and method2using different locks lockone and locktwo, then threadA can access method1, at the same time thread Bcan access method2?
Yes, if method1 and method2 using the same lock, then thread A and B cannot access method1 or method 2 at same time. But if methods using different locks, then thread A and B will not be able to access same methods, but accessing different methods will work. That is, thread A and B can't access same method1, or same method2. But while thread A accessing method1, thread B can access method2.
why don't we lock each method separately instead of putting them in one lock?
If you want any threads to block method 2 from accessing, till first thread has not finished access / executtion of method1 and method2, then given code sample is correct.
Example:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Main implements Runnable {
private Lock lock = new ReentrantLock();
public void method1() throws InterruptedException {
System.out.println(Thread.currentThread().getName() + " entered method1.");
Thread.sleep(1000);
lock.lock();
System.out.println(Thread.currentThread().getName() + " ackquired lock.");
Thread.sleep(1000);
}
public void method2() {
System.out.println(Thread.currentThread().getName() + " entered method2.");
lock.unlock();
System.out.println(Thread.currentThread().getName() + " released lock.");
}
public void run() {
try{
method1();
}catch(Exception e){
e.printStackTrace();
}finally{
method2();
}
}
public static void main(String [] args) {
Runnable runnable = new Main();
new Thread(runnable, "ThreadA").start();
new Thread(runnable, "ThreadB").start();
}
}
If you use the same lock for both methods, then if thread-1 is executing method-1 (i.e, after acquiring the lock), then no other thread can execute method-1 as well as method-2.
If you use 2 different locks for 2 methods, then if thread-1 and thread-2 are executing method-1 and method-2 by acquiring lock on lock-1 and lock-2 respectively, then other threads can execute method-1 if thread-1 releases the lock and method-2 if thread-2 releases the lock.
why don't we, or can we make method1 and 2 into one critical section by only acquiring the lock in methos1, and releasing the lock after method2?
Because it's bad design.
The office where I work has hundreds of thousands of lines of Java code to maintain. Some of it's been around for as long as ten years, and developers have been coming and going and working in that code all that time. Adherence to strict style rules and strict conventions is an important part of how we keep it all safe and sane and mostly bug-free.
If we use a ReentrantLock, we use always use it just how you used it in your first example:
lockone.lock();
try {
// do something
} finally {
lockone.unlock();
}
If there's a methodOne, and a methodTwo, and there's a need to call them both atomically, then we write it like this:
private methodOne(...) { ... }
private methodTow(...) { ... }
public callMethodOneAndMethodTwo(...) {
lockOneTwo.lock();
try {
methodOne(...);
methodTwo(...);
} finally {
lockOneTwo.unlock();
}
This way of managing the lock guarantees that no thread can ever fail to unlock the lock after it's done what it needs to do. It guarantees that no other function in any other package can call methodOne() without subsequently calling methodTwo(). It guarantees that no such function can call methodTwo() without first calling methodOne(). It's easier to understand, and it's easier to maintain.
If I synchronized two methods on the same class, can they run simultaneously on the same object? For example:
class A {
public synchronized void methodA() {
//method A
}
public synchronized void methodB() {
// method B
}
}
I know that I can't run methodA() twice on same object in two different threads. same thing in methodB().
But can I run methodB() on different thread while methodA() is still running? (same object)
Both methods lock the same monitor. Therefore, you can't simultaneously execute them on the same object from different threads (one of the two methods will block until the other is finished).
In the example methodA and methodB are instance methods (as opposed to static methods). Putting synchronized on an instance method means that the thread has to acquire the lock (the "intrinsic lock") on the object instance that the method is called on before the thread can start executing any code in that method.
If you have two different instance methods marked synchronized and different threads are calling those methods concurrently on the same object, those threads will be contending for the same lock. Once one thread gets the lock all other threads are shut out of all synchronized instance methods on that object.
In order for the two methods to run concurrently they would have to use different locks, like this:
class A {
private final Object lockA = new Object();
private final Object lockB = new Object();
public void methodA() {
synchronized(lockA) {
//method A
}
}
public void methodB() {
synchronized(lockB) {
//method B
}
}
}
where the synchronized block syntax allows specifying a specific object that the executing thread needs to acquire the intrinsic lock on in order to enter the block.
The important thing to understand is that even though we are putting a "synchronized" keyword on individual methods, the core concept is the intrinsic lock behind the scenes.
Here is how the Java tutorial describes the relationship:
Synchronization is built around an internal entity known as the intrinsic lock or monitor lock. (The API specification often refers to this entity simply as a "monitor.") Intrinsic locks play a role in both aspects of synchronization: enforcing exclusive access to an object's state and establishing happens-before relationships that are essential to visibility.
Every object has an intrinsic lock associated with it. By convention, a thread that needs exclusive and consistent access to an object's fields has to acquire the object's intrinsic lock before accessing them, and then release the intrinsic lock when it's done with them. A thread is said to own the intrinsic lock between the time it has acquired the lock and released the lock. As long as a thread owns an intrinsic lock, no other thread can acquire the same lock. The other thread will block when it attempts to acquire the lock.
The purpose of locking is to protect shared data. You would use separate locks as shown in the example code above only if each lock protected different data members.
Java Thread acquires an object level lock when it enters into an instance synchronized java method and acquires a class level lock when it enters into static synchronized java method.
In your case, the methods(instance) are of same class. So when ever a thread enters into java synchronized method or block it acquires a lock(the object on which the method is called). So other method cannot be called at the same time on the same object until the first method is completed and lock(on object) is released.
In your case you synchronized two method on the same instance of class. So, these two methods can't run simultaneously on different thread of the same instance of class A. But they can on different class A instances.
class A {
public synchronized void methodA() {
//method A
}
}
is the same as:
class A {
public void methodA() {
synchronized(this){
// code of method A
}
}
}
Think of your code as the below one:
class A {
public void methodA() {
synchronized(this){
//method A body
}
}
public void methodB() {
synchronized(this){
// method B body
}
}
So, synchronized on method level simply means synchronized(this).
if any thread runs a method of this class, it would obtain the lock before starting the execution and hold it until the execution of the method is finished.
But can I run methodB() on different thread while methodA() is still
running? (same object)
Indeed, it is not possible!
Hence, multiple threads will not able to run any number of synchronized methods on the same object simultaneously.
From oracle documentation link
Making methods synchronized has two effects:
First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads
This will answer your question: On same object, You can't call second synchronized method when first synchronized method execution is in progress.
Have a look at this documentation page to understand intrinsic locks and lock behavior.
Just to all clarity, It’s possible that both static synchronized and non static synchronized method can run simultaneously or concurrently because one is having object level lock and other class level lock.
The key idea with synchronizing which does not sink in easily is that it will have effect only if methods are called on the same object instance - it has already been highlighted in the answers and comments -
Below sample program is to clearly pinpoint the same -
public class Test {
public synchronized void methodA(String currentObjectName) throws InterruptedException {
System.out.println(Thread.currentThread().getName() + "->" +currentObjectName + "->methodA in");
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + "->" +currentObjectName + "->methodA out");
}
public synchronized void methodB(String currentObjectName) throws InterruptedException {
System.out.println(Thread.currentThread().getName() + "->" +currentObjectName + "->methodB in");
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + "->" +currentObjectName + "->methodB out");
}
public static void main(String[] args){
Test object1 = new Test();
Test object2 = new Test();
//passing object instances to the runnable to make calls later
TestRunner runner = new TestRunner(object1,object2);
// you need to start atleast two threads to properly see the behaviour
Thread thread1 = new Thread(runner);
thread1.start();
Thread thread2 = new Thread(runner);
thread2.start();
}
}
class TestRunner implements Runnable {
Test object1;
Test object2;
public TestRunner(Test h1,Test h2) {
this.object1 = h1;
this.object2 = h2;
}
#Override
public void run() {
synchronizedEffectiveAsMethodsCalledOnSameObject(object1);
//noEffectOfSynchronizedAsMethodsCalledOnDifferentObjects(object1,object2);
}
// this method calls the method A and B with same object instance object1 hence simultaneous NOT possible
private void synchronizedEffectiveAsMethodsCalledOnSameObject(Test object1) {
try {
object1.methodA("object1");
object1.methodB("object1");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// this method calls the method A and B with different object instances object1 and object2 hence simultaneous IS possible
private void noEffectOfSynchronizedAsMethodsCalledOnDifferentObjects(Test object1,Test object2) {
try {
object1.methodA("object1");
object2.methodB("object2");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Notice the difference in output of how simultaneous access is allowed as expected if methods are called on different object instances.
Ouput with noEffectOfSynchronizedAsMethodsCalledOnDifferentObjects() commented -the output is in order methodA in > methodA Out .. methodB in > methodB Out
and Ouput with synchronizedEffectiveAsMethodsCalledOnSameObject() commented -
the output shows simultaneous access of methodA by Thread1 and Thread0 in highlighted section -
Increasing the number of threads will make it even more noticeable.
You are synchronizing it on object not on class. So they cant run simultaneously on the same object
No it is not possible, if it were possible then both method could be updating same variable simultaneously which could easily corrupt the data.
Yes, they can run simultaneously both threads. If you create 2 objects of the class as each object contains only one lock and every synchronized method requires lock.
So if you want to run simultaneously, create two objects and then try to run by using of those object reference.
Two different Threads executing a common synchronized method on the single object, since the object is same, when one thread uses it with synchronized method, it will have to verify the lock, if the lock is enabled, this thread will go to wait state, if lock is disabled then it can access the object, while it will access it will enable the lock and will release the lock
only when it's execution is complete.
when the another threads arrives, it will verify the lock, since it is enabled it will wait till the first thread completes his execution and releases the lock put on the object, once the lock is released the second thread will gain access to the object and it will enable the lock until it's execution.
so the execution will not be not concurrent, both threads will execute one by one, when both the threads use the synchronized method on different objects, they will run concurrently.