Java lock objects in one class - java

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.

Related

Thread.sleep is blocking other thread also, working on other method, along with itself callled inside synchronized method

class Common
{
public synchronized void synchronizedMethod1()
{
System.out.println("synchronized Method1 called");
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println("synchronized Method1 done");
}
public synchronized void synchronizedMethod2()
{
System.out.println("synchronized Method2 called");
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println("synchronized Method2 done");
}
}
In the above class I have two synchronized methods which I am calling from run method of another class. Other class code is given below:
public class ThreadClass implements Runnable
{
private int id = 0;
private Common common;
public ThreadClass(int no, Common object)
{
common = object;
id = no;
}
public void run()
{
System.out.println("Running Thread " + Thread.currentThread().getName());
try
{
if (id == 11)
{
common.synchronizedMethod1();
}
else
{
common.synchronizedMethod2();
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
Common c = new Common();
ThreadClass tc = new ThreadClass(11, c);
ThreadClass tc1 = new ThreadClass(20, c);
Thread t1 = new Thread(tc, "Thread 1");
Thread t2 = new Thread(tc1, "Thread 2");
t1.start();
t2.start();
}
}
From main method I am starting two different threads. In run method I have given a condition to send both different threads to different synchronized methods. Output produced by the code is:
Running Thread Thread 2
Running Thread Thread 1
synchronized Method2 called
synchronized Method2 done
synchronized Method1 called
synchronized Method1 done
MY QUESTION FOR THE OUTPUT IS:
When thread 2 goes to synchronized Method2 it prints 3rd line of output and goes to sleep for 1 second. Now since thread 1 is not blocked by anything so it should execute and print 5th line of the output just after 3rd line of output and should go to sleep then but this is not happening instead when thread 2 goes to sleep it make's thread 1 also sleep then first thread 2 complete's its execution after which thread 1 completes its execution.
Such a behavior is not happening if I remove synchronized keyword from methods.
Can you please explain me the reason behind different way of processing the code with and without synchronized keywords.
Thanks in advance.
Such a behavior is not happening if I remove synchronized keyword from methods. Can you please explain me the reason behind different way of processing the code with and without synchronized keywords.
This is actually the entire purpose of the synchronized keyword. When you have several synchronized instance methods of the same class, only one may be executing at a time. You have written this:
class Common {
public synchronized void synchronizedMethod1(){}
public synchronized void synchronizedMethod2(){}
}
Because both methods are synchronized, only one may be executed at once. One of them can't start the other one is done.
How does this work? In short, you have a Common object and call a synchronized instance method of it. When you call synchronzedMethod1, that method will "lock" the Common object (called "acquiring the lock"). While that method has that lock on that Common object, if you try to call any other synchronized method on that same object, it will try to lock it and it will find that it's already locked. So any other attempt to lock the object will hang until they can do so. Once synchronizedMethod1 finishes, it will unlock the Common object (called "releasing the lock") and anybody can then try to lock it, such as synchronzedMethod2.
So in short, synchronized specifically makes it so you can't have two synchronized methods of the same class happening at once. This is useful because some problematic behavior can come from not doing this. As an example, ArrayList does not do this, so if one thread tries to add an object to an ArrayList while another tries to iterate over it, it might throw a ConcurrentModificationException and make everyone sad.
A sleeping thread does not release its locks, but you can replace your sleep(...) calls with wait(...). Keep in mind, though, that only the lock of the object having wait(...) called on it will be released, so you'd have to devise a different solution if you expected multiple locks to be released while waiting.
synchronising a method doesnt mean just the method itself synchronised
synchronized void x(){}
equals to:
void x(){
synchronised(this){}
}
Since both thread access same Common instance first thread will get the ownership of the Common object lock doesnt matter which synchronised method called and it will just release this lock after this method body completed its job.
If you would send two Common instance there would not be a problem since they are not static. Also you might be interested in ReentrantLock
First of all synchronized keyword is used to define mutual exclusion. Here mutual exclusion achieved by Monitor concept. One more thing is sleep does not release monitor. It just pause the execution of current thread for some time. Other threads which requires the monitor have to wait until the thread which acquired monitor release it.
There is two ways to use synchronized...
First one is using synchronized blocks.
synchronized(obj){...}
Here if any thread want to enter into synchronized block it have to get monitor of obj.
Second one is to using synchronized method.
synchronized void meth(){...}
Main difference between synchronised method & block is synchronised method use monitor of object it self & synchronised block can have monitor of any object.
Synchronized method can be defined using synchronized block as follows...
void meth(){
synchronized (this){
//method body
}
}
Now you can use the synchronised block to prevent the problem of blocking another method. Here you have to define synchronised block on different objects so both methods can execute concurrently but multiple threads can not execute same method concurrently.

Java: calling a method from the main thread by signaling in some way from another thread

I have an application with 2 threads (the main and another thread t1) which share a volatile variable myVar. Any ideas on how to make the main thread to call a method myMethod by signaling in some way from t1 ?
I implemented it by using ChangeListener and myMethod is called when myVar changes, BUT the method is called from t1, and not from the main thread (note: I need to call this method from the main thread because this is a call to a JavaScript code from Java, so for a security reason only the main thread can do so). Thanks in advance.
You would have to have your main thread spin in a loop on some scalar, I would recommend one of the Atomics that java provides (http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/package-summary.html), but you could use volatile if you wanted for this I think.
Each thread can only run sequentially - it's just the way computing works. The way you will handle this, is when the main thread spins in some sort of loop, you eventually check to see if this scalar of yours has been set, and when it has, you want unset the variable and execute your JavaScript. In this particular piece of your code, I think the Atomics have an advantage over the volatile with the use of the compareAndSet operations because using volatile can mess you up a bit between threads if you are trying to check the value in one operation and then set it again in another operation which gives the other thread enough time to set it again - meaning you may miss a call to your JS because the other thread set the variable between the main thread checking it and setting it (although the use of volatile vs Atomics may be interpreted as my opinion).
//main thread
AtomicBoolean foo = new AtomicBoolean(false);
while (...somecondition...){
if(foo.compareAndSet(true, false)){
//execute JS
}
//do some other work
}
and in your T1 thread, just call foo.set(true).
If you expect main to call your JS for each time T1 sets foo to true, then you will have to block in T1 until main has unset foo, or use an AtomicInteger to count how many times T1 has set foo - depending on your needs.
Since both tread sharing the same instance of myVar, you can make both thread to synchronize on the shared variable. Have main to wait on myVar notification before executing myMethod. Later, t1 can notify through variable myVar, and the waiting thread can continue and proceed with the method call.
The following snippet fully demonstrated the idea
public class MainPlay {
public static void main(String[] args) {
MainPlay mp = new MainPlay();
mp.execute();
}
public void execute() {
Thread main = new Thread(mainRunnable, "main");
Thread t1 = new Thread(t1Runnable, "t1");
main.start();
t1.start();
}
public Object myVar = new Object();
public void myMethod() {
System.out.println("MyMethodInfoked.");
}
public Runnable t1Runnable = new Runnable() {
public void run() {
synchronized(myVar) {
try {
System.out.println("[t1] sleep for 1 sec");
Thread.sleep(1000);
System.out.println("[t1] Notifying myVar so Main can invoke myMethod");
myVar.notify();
} catch (InterruptedException e) {
// interupted.
}
}
}
};
public Runnable mainRunnable = new Runnable() {
public void run() {
synchronized(myVar) {
try {
System.out.println("[main] Waiting for t1 to notify...");
myVar.wait();
} catch (InterruptedException e) {
// interrupted.
}
System.out.println("[main] executing main method");
myMethod();
}
}
};
}
And the output is
[main] Waiting for t1 to notify...
[t1] sleep for 1 sec
[t1] Notifying sharedObject so Main can invoke myMethod
[main] executing main method
MyMethodInfoked.
You could use wait/notify blocks to prevent the main thread from continuing until signalled to do so.
static Main main = // ...
static boolean signal = false;
// t1:
// Do work
signal = true;
synchronized (main) {
main.notify();
}
// main:
synchronized (main) {
while (!signal) {
main.wait();
}
}
myMethod();
In case the main thread has nothing else to do, the approach proposed by #searchengine27 results in unnecessary processor load generated by this thread.
So instead going with some AtomicXXX class it would be better to use some of the blocking queues which allow writing of data from one thread (with put()) and consumption of that data by the other. The main queue would block (by calling take() method) if such a queue is empty not using any CPU resources.

If I synchronized two methods on the same class, can they run simultaneously?

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.

Java - synchronizing static methods

Here is a piece of text I found at this link.
"Avoid lock on static methods
The worst solution is to put the "synchronized" keywords on the static
methods, which means it will lock on all instances of this class."
Why would synchronizing a static method lock all instances of the class? Shouldn't it just lock the Class?
To understand this, the easiest way is to compare how lock works against instance method and static method.
Let's say you have class Test.java, which has two methods as follow.
public class Test{
public synchronized void instanceMethod(){
}
public synchronized static void staticMethod(){
}
}
Meanwhile, there are two instances of class Test, testA and testB. And also there are two thread tA and tB trying to access class Test in parallel.
locking on instanceMethod:
When tA gets the lock on instanceMethod of testA, tB cannot access the the same method in testA, however tB is still free to invoke instanceMethod in testB. Because the synchronization against instanceMethod is instance level locking
locking on staticMethod:
However, when tA gets the lock on staticMethod, the lock has nothing to do with testA or testB, since synchronization on static method is a class level locking. Which means tB cannot access staticMethod at all until tA release the lock
Actually a lock on a static method of class Foo, is the same as putting a lock on Foo.class (which is the only instance):
public static void doSomething()
{
synchronized(Foo.class)
{
// ...
}
}
Here's my test code that shows that you're right and the article is a bit over-cautious:
class Y {
static synchronized void staticSleep() {
System.out.println("Start static sleep");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
System.out.println("End static sleep");
}
synchronized void instanceSleep() {
System.out.println("Start instance sleep");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
System.out.println("End instance sleep");
}
}
public class X {
public static void main(String[] args) {
for (int i = 0; i < 2; ++i) {
new Thread(new Runnable() {
public void run() {
Y.staticSleep();
}
}).start();
}
for (int i = 0; i < 10; ++i) {
new Thread(new Runnable() {
public void run() {
new Y().instanceSleep();
}
}).start();
}
}
}
Prints:
Start instance sleep
Start instance sleep
Start instance sleep
Start instance sleep
Start instance sleep
Start static sleep
Start instance sleep
Start instance sleep
Start instance sleep
Start instance sleep
Start instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End instance sleep
End static sleep
Start static sleep
End static sleep
So the static synchronized has no bearing on the synchronized methods on the instances...
Of course if static synchronised methods are used throughout the system, then you can expect them to have the most impact on the throughput of a multithreaded systems, so use them at your peril...
You are right — the actual lock is on the Class instance itself, not on any instance of the class (let alone all instances) — but I think you're interpreting the linked page too literally. It itself uses the phrase "a static lock (a Class lock)", so clearly its author is aware of how the locking works. But if you have many instances in different threads that are all using synchronized static methods, then those instances will all lock each other out. The synchronized static methods won't cause blocking of synchronized instance methods, but the problem is there regardless.
It doesn't say 'lock all instances of the class'. It says 'lock on all instances of the class. It's poorly worded, indeed incorrect, but it doesn't it say what you said it said.
A synchronized method acquires a monitor (§17.1) before it executes. For a class (static) method, the monitor associated with the Class object for the method's class is used. For an instance method, the monitor associated with this (the object for which the method was invoked) is used.
http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.3.6

Why is this thread allowing another one to access its synchronized method?

I have the following codes. I expected one thread to execute its synchronized method completely and then allow another one to access the same method. However, this is not the case.
public class Threads {
/**
* #param args
*/
public static void main(String[] args) {
//Thread Th = new Threads();
Thread th = new Thread (new thread1 ());
th.start();
Thread th1 = new Thread (new thread1 ());
th1.start();
}
}
class thread1 implements Runnable{
String name = "vimal";
public void run() {
System.out.println("Runnable "+this.name);
setNAme("Manish");
}
public synchronized void setNAme(String name){
try {
System.out.println("Thread "+Thread.currentThread().getName());
wait(1000);
this.name = name;
System.out.println("Name "+this.name);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I have one output as
Runnable vimal
Thread Thread-0
Runnable vimal
Thread Thread-1
Name Manish
Name Manish
What is the use of synchronized here and how do I make my method to run completely before another accesses it?
synchronized has no effect here because you are not synchronizing on the same object in both cases. When applied to an instance method, the synchronized keyword causes the method to be synchronized on this. So in each case you are synchronizing on the instance of thread1, and there are two of those.
The more interesting test would be when you run the same instance of thread1 in two threads simultaneously. In that case, calling wait(1000) is a very bad thing to do because (as documented) it releases the lock on this. You want to use Thread.sleep(1000) instead in your code.
If you need to have two instances of thread1, you need to synchronize on some shared object, possibly like this:
private static final Object lockObject = new Object();
public void setName(String newName) {
synchronized(lockObject) {
doSetName(newName);
}
}
You will have to remove the call to wait(1000). It looks like what you actually want is a call to Thread.sleep(1000), if you simply want to pause the current thread, this does not release ownership of any monitors.
From the javadoc for Object.wait().
This method causes the current thread (call it T) to place itself in
the wait set for this object and then to relinquish any and all
synchronization claims on this object. Thread T becomes disabled for
thread scheduling purposes and lies dormant until one of four things
happens:
Some other thread invokes the notify method for this object and thread T happens to be arbitrarily chosen as the thread to be
awakened.
Some other thread invokes the notifyAll method for this object.
Some other thread interrupts thread T.
The specified amount of real time has elapsed, more or less. If timeout is zero, however, then real time is not taken into
consideration and the thread simply waits until notified.
The thread T is then removed from the wait set for this object and
re-enabled for thread scheduling. It then competes in the usual manner
with other threads for the right to synchronize on the object; once it
has gained control of the object, all its synchronization claims on
the object are restored to the status quo ante - that is, to the
situation as of the time that the wait method was invoked. Thread T
then returns from the invocation of the wait method. Thus, on return
from the wait method, the synchronization state of the object and of
thread T is exactly as it was when the wait method was invoked.
UPDATE: As has been mentioned in other answers, you are not synchronizing on the same object. Once you do, you will still suffer the same output, due to the issue I have mentioned. You will need to fix both for your desired results.
The output is correct, you are creating to independent threads that do not share any data. Thus both threads start with first string, and after some time, the string is changed and printed.
You're creating 2 thread1 objects. They each have their own setNAme method. Synchronized methods only synchronize on the object, not the class. Unless the method is static.
You have two Threads here with independent name variables and independent monitors, so each Thread is only accessing its own members. If you want to have the threads interact with each other you'll have to implement such an interaction.
you are creating two separate thread1 objects and running them. Each thread has it's own copy of the name variable as well as the setName function. Make them both static and you will see the effects of synchronization.
You are locking on two different instance of the objects where you dont need any synchronization at all. You need to synchronize only if you are working on a shared data. I think you meant to write a test like the below.
If you test this, you will realize that the second thread will wait until the first thread is completed with the synchronized method. Then take out the synchronized word and you will see both threads are executing at the same time.
public class SynchronizeTest {
public static void main(String[] args) {
Data data = new Data();
Thread task1 = new Thread(new UpdateTask(data));
task1.start();
Thread task2 = new Thread(new UpdateTask(data));
task2.start();
}
}
class UpdateTask implements Runnable {
private Data data;
public UpdateTask(Data data) {
this.data = data;
}
public void run() {
try {
data.updateData();
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Data {
public synchronized void updateData() throws InterruptedException {
for (int i = 0; i < 5; i++) {
Thread.sleep(5000);
System.out.println(i);
}
}
}

Categories