Java Thread : object has both synchronized and not synchronized methods - java

suppose there are 2 threads used in this demo.Suppose increment() code block executes first and acquires the monitor on the current object.does other thread will not be able to execute the method decrement() ? .
can anyone help me understand?
if I ran the application, other thread able to execute non-synchronized method even though is lock on the object hold by thread that sleeps 10000 ms .
package com.learn.threads;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadDemo {
int sharedVariable;
public ThreadDemo(int sharedVariable) {
this.sharedVariable = sharedVariable;
}
public synchronized void increment() throws InterruptedException {
Thread.sleep(10000);
this.sharedVariable++;
}
public void decrement() throws InterruptedException {
this.sharedVariable--;
}
public static void main(String[] args) throws InterruptedException {
ThreadDemo task = new ThreadDemo(0);
ExecutorService incrementExecutorService = Executors.newFixedThreadPool(2);
for (int i = 0; i < 6; i++) {
incrementExecutorService.submit(() -> {
try {
task.increment();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread.sleep(5000);
incrementExecutorService.submit(() -> {
try {
task.decrement();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
Thread.sleep(35000);
incrementExecutorService.shutdown();
System.out.println(task.sharedVariable);
}
}

No, it won't.
synchronized on a method is just syntax sugar for wrapping the entire body of the method in synchronized (X) {}, where X is this for instance methods and YourClass.class for static ones. It is a severe design error unless you document the locking behaviour of your class if you do this - anytime you lock on stuff other code could get a reference to (this and YourClass.class are usually public), you need to document this, and endeavour to support what you document in future v ersion.
synchronized interacts with other synchronized blocks on the same reference, and on thatRef.wait/notify/notifyAll() and nothing else. It has zero effect on its own, you always need 2 different threads both hitting a synchronized block, synchronizing on the same thing, or it does nothing useful.
The code snippet as pasted is broken: If some thread calls decrement(), other threads may or may not observe this, as no CBCA relationship is established. Any code that reads sharedVariable needs to lock on ThreadDemo, and the decrement method needs to gain a synchronized attribute.
Note that the job of having an incrementable/decrementable thing already exists: AtomicInteger, you should be using that instead if this is your actual intent (but I'm assuming you wrote this merely as an example).
NB: The java memory model is best understood as an evil coin. Evil in that it is out to mess with you: To have code that works great every time and in all your tests, and the first week you put it live on the production servers, and then just as that important customer gets a demo, it breaks. You must write code such that the VM never flips that coin (or rather, that the results of the flip do not affect your code), and there is no easy way to know that the evil coin is being flipped. Threading is very difficult to get right, yup. Why do you think most multithreaded code out in the real world does all inter-thread communication via a message bus or transactional database? The coin is flipped anytime any code touches any field anywhere, and the result of the coin decides whether the thread uses a local clone copy of that field, or if it reads from the shared copy. Thus, sharedVariable-- might result in a decrement that only your thread can see, or all threads can see, depending on the result of the evil coin. If what your code does depends on the flip, you messed up, and your tests aren't going to catch it. You can avoid the coin flip by establishing a comes-before relationship between sharedVariable-- and whatever cod reads sharedVariable. synchronized is one of a few ways to establish such a relationship. Search the web for 'java memory model' 'synchronized' for more info - but note that this is very complex stuff.

Related

Java locking methods

How can I lock a method until an other method is invoked?
public class TestLock{
public void methodIsLockedAfterFirstCall(){
doSomething();
//now lockThisMethod (when invoked, the thread shall sleep)
}
public void methodToDoSomethingAfterTheFirstMethod(){
doSomeOtherThing()
//unlock the first Method?
}
}
Is there something already in Java for this or should I do it some way around ( e.g. Boolean or AtomicLong)?
If you want to build this up from base principles you'd do something like:
private final AtomicBoolean lock = new AtomicBoolean();
public void methodIsLockedAfterFirstCall() {
doSomething();
synchronized (lock) {
while (lock.getAndSet(true)) try {
lock.wait();
} catch (InterruptedException e) {
return; // SEE NOTE 1
}
}
}
public void methodToDoSomethingAfterTheFirstMethod() {
doSomeOtherThing();
synchronized (lock) {
lock.set(false):
lock.notifyAll();
}
}
This code:
Uses a private lock. Locking om something public is only acceptable if you document this behaviour and maintain this behaviour for future versions (or mark your new version as utterly incompatible with the old). As a rule, public locks are an error. synchronizing on this, therefore, is usually wrong. This code locks on a private variable.
This code does not run afoul of JMM issues by using AtomicBoolean.
NOTE 1: InterruptedException only ever occurs if you (or other code running on the JVM) explicitly calls .interrupt() on the thread (it does not occur if e.g. the user hits CTRL+C, or killall YourProcess, or 'end task' in the task manager, or any other way that doesn't involve code running in that VM that calls .interrupt(). What to do? Well, do not just e.printStackTrace(), the usual mainstay of java programmers who no idea what they are doing. What did you want to happen when you write thread.interrupt(), somewhere else in the codebase? Do that. If the notion of 'stop waiting for that second call now' is a sensible idea, then document the behaviour in this method. Here I've chosen to just return (stop waiting), but keep the lock in locked state.
Does not use notify/wait as a mechanism to communicate data; only as a mechanism to communicate when to wait and when to stop waiting. This is generally a good idea, it can be very hard to debug relevant state when that state is captured by 'were you notified or not', and makes it impossible to use the wait(timeout) variant. That's why there is a while loop. Being woken up just results in trying to getAndSet again, which can reuslt in waiting some more. That's a good thing.
Or, use something from j.u.concurrent. Some ideas:
A Lock which the first method locks and the second method unlocks.
A Semaphore doesn't sound right, as .release() will add 1 to the count, always, so if you call the second method whilst the 'lock status' is UNLOCKED, you'd erroneously be adding a permit. You can't do if (semaphore.availablePermits() < 1) semaphore.release(); as that'd have a race condition unless you do this in a synchronized block which kinda defeats the purpose.
There is a lot under the java.util.concurrent.locks and java.util.concurrent packages.
Maybe CountDownLatch is the easier one to use:
private final CountDownLatch latch = new CountDownLatch(1);
public class TestLock{
public void methodIsLockedAfterFirstCall() throws InterruptedException {
doSomething();
//now lockThisMethod (when invoked, the thread shall sleep)
latch.await()
}
public void methodToDoSomethingAfterTheFirstMethod(){
doSomeOtherThing()
//unlock the first Method?
latch.countDown();
}
}

Purpose of different monitor objects in synchronized

Could someone explain the difference between synchronized(this) and synchronized (c)?
I refereed various answers(1,2,3,4,5) but not able to understand and getting confused.
public class Check {
Consumer c = new Consumer(null);
public void getSynch() {
synchronized (this) {
// doing some task
System.out.println("Start");
}
synchronized (c) {
// doing some task
System.out.println("End");
}
}
}
I am able to understand the synchronized concept but not monitor object. Please explain in a simple way.
synchronized always works on a monitor object (sometimes also called lock or semaphore). Think of it as a token: when a thread enters a synchronized block it grads the token and other threads need to wait for the token to be returned. If you have multiple different monitor objects you basically have different tokens and thus synchronized blocks that operate on different monitors can run in parallel.
There are many possibilities with this and many possible use cases. One could be that multiple instances of a class could run in parallel but need access to a shared and non-threadsafe resource. You then could use that resource or any other object that represents the "token" for that resource as the monitor object.
However, note that there's potential for deadlocks, e.g. in the following situation:
Block 1:
synchronized(A) {
//do something with A
synchronized(B) {
//do something with B
}
}
Block 2:
synchronized(B) {
//do something with B
synchronized(A) {
//do something with A
}
}
Here both outer synchronized blocks could be entered in parallel because the two monitors A and B are available but then need to grab the other monitor and because they are now locked both threads would have to wait - class deadlock.
Also have a look at the dining philosophers problem which handles that topic as well (here the forks could be considered the monitor objects).
Edit:
In your case (the code you've posted), multiple threads could try to call getSynch() on the same instance of Check. The first block synchronizes on the instance itself thus preventing multiple threads from entering that block if called on the same instance.
The second block synchronizes on c which is a different object and could change over time. Assume the first block (synchronized(this) { ... }) changes c to reference another instance of Consumer. In that case you could have multiple threads run that block in parallel, e.g. if one entered the synchronized(c) block before the other thread reassigns c.

Will a variable be read "fresh from main memory" if used in a loop AROUND a synchronized lock?

Please see the code below:
private static boolean flag=true; // main thread will call flag=false
private final static Object lock=new Object(); // lock condition
public static void thread1(){
while (flag){
synchronized (lock){
// some work
}
}
}
public static void main(String[] args) throws Exception {
Thread t1=new Thread(()->{
thread1();
});
t1.start();
Thread.sleep(1000);
flag=false;
// The program can stop normally
}
No matter at any time , When one thread entering the synchronized block, will the value of the variable flag be loaded from main memory?
Thank you for your detailed explanation, because I am not sure if the flag has a happend-befores relationship. Literally, the flag is not in the synchronized block.
Update1:
I know that using volatile can and I also know how to write the right code,, but I want to know now if there is no volatile keyword. Whether synchronized can guarantee visibility. Note: the flag variable is not in synchronized block.
Update2:
I updated the code again, the code on my win10+JDK8 system can stop normally, do you think it is correct or accidental, because it is not tested on all hardware systems, so I need theory to guide。
Focus on the question:
whether the loop condition (flag variable) has a happen-before relationship with the synchroized block inside the loop,If it has a happen-before relationship, jvm whether ensure that the flag variable is loaded from main memory even if the flag variable is not in the synchronized block.
If every one think there is no happen-before relationship, then how do you explain that when I remove the synchronized block, the code will loop indefinitely. When I add it, it will stop normally. Is this just an accident?
OK looking a little more closely at your code, what you have is not enough. The access to a shared field is outside of your synchronized block, so no it does not work.
In addition, Java requires that both the read and the write of shared memory be "synchronized" somehow. Using the synchronized keyworld, that usually means you need to use it on both the read and the write, and you did not show the write.
And in addition to that, the "lock" that you use for a given set of fields or shared memory must be the same lock for both the read and the write. Seriously, volatile is a lot easier here, and the API in java.util.concurrent is even easier and recommended. Don't try reinventing the wheel.
private static boolean flag = true; // must use 'resetFlag'
public void resetFlag() { synchronized( "lock" ) {flag = false;} }
public boolean getFlag() { synchronized( "lock" ) {return flag;} }
public void thread1() {
while ( getFlag() ){
synchronized ("lock"){
// other work
}
}
}
public static void main(String[] args) throws Exception {
Thread t1=new Thread(()->{
thread1();
});
t1.start();
Thread.sleep(1000);
resetFlag();
// The program can stop normally
}
I think the above has the required changes.
Regarding your second update: the code on my win10+JDK8 system can stop normally Yes it can. Memory visibility is not guaranteed, but it is not prohibited. Memory can be made visible for any reason, even just "accidentally." On Intel platforms, Intel has a QPI bus which exchanges memory update information at high speed, bypassing the memory bus. However even that can be got around by software, so it's best to just put the synchronization where needed (Hint: look at AtomicBoolean.)
Thanks to the information provided by #xTrollxDudex and #markspace ,The code in the loop section is observed from the jvm level, If there is no
happens-before relationship and the code may be optimized from :
while (flag){
synchronized (lock){
// some work
}
}
to :
if(flag){
while (true){
synchronized (lock){
//some work
}
}
}
To ensure thread visibility, we need to avoid this optimization, such as through the volatile keyword or other synchronization strategies.
The appearance of the sync block in the loop is similar to the function of the enhanced volatile keyword, which guarantees the visibility of the variable in front of it, so when we loop into the sync block for the second time, we can see it latest. The change, which is why the loop can stop normally. It looks fine, but it's not the right synchronization method, so don't do it.
For a detailed explanation, please see a similar question in here

Killing a thread or an asynchronous task

let's say I use a jar that IBM has created.
Let's say that this Jar has a function that I need but is ultimately build as such:
while (true) {
System.out.println(1)
}
(of course it doesn't really just printing 1, but for the example let's say it is)
So, I made the call to the function that does it in another thread using future. How can I completely kill the thread that this code is running in? Or alternatively, how can I kill the asynchronous task in Kotlin that runs the code.
Solutions in Kotlin or Java will be great,
thanks in advance!
EDIT:
I've found out, that if this is a thread, I can Thread#stop() it to really make it stop. But unfortunately making the constructor throwing exceptions multiple times, causes the JVM to erase the class from memory causing a NoClassDefFoundError when instantiating the class the next time..
If you can capture it's thread you should be able to kill it so long as it is doing some kind of blocking function internally.
class OtherFunction implements Runnable {
#Override
public void run() {
while(true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// We assume the thread will exit when interrupted.
System.out.println("Bye!!");
return;
}
System.out.println("Hello");
}
}
}
class Killable implements Runnable {
final Runnable target;
private Thread itsThread;
Killable(Runnable target) {
this.target = target;
}
#Override
public void run() {
// Catch the thread id of the target.
itsThread = Thread.currentThread();
// Launch it.
target.run();
}
public void kill() {
// Give it a good kick.
itsThread.interrupt();
}
}
public void test() throws InterruptedException {
OtherFunction theFunction = new OtherFunction();
Killable killableVersion = new Killable(theFunction);
new Thread(killableVersion).start();
// Wait for a few seconds.
Thread.sleep(10000);
// Kill it.
killableVersion.kill();
}
It seems like Thread#stop() solved my problem. I know it's deprecated and can be prevented with catch(Throwable t) but at least it did the trick for me.
By the way, to get the thread from the executor, I've used AtomicReference<Thread> and set it in the callback.
Thread#stop() is deprecated as 'inherently unsafe' and should be avoided if at all possible.
It's a source of instability and corruption and may fail anyway!
It actually causes a ThreadDeath exception to be throw in the target thread.
The authors of whatever code it pops into are unlikely to have expected that outcome.
Objects may be in an inconsistent state, external resources may be held and get leaked, files may be incompletely written.
There are ways of handling unexpected errors but in practice most code is written assuming it knows which exceptions might be thrown and not in anticipation for such a 'surprise'.
Given ThreadDeath is a Throwable any catch(Throwable t) will catch it and again, unless great care was taken in every piece of code the thread might execute (unrealistic) ThreadDeath might just get absorbed and not end the thread.
The correct way to handle this is declare an atomic variable (usually as part of the Runnable that represents the task.
AtomicBoolean stopThread=new AtomicBoolean(false);
Then write the loop as:
while (!stopThread.get()) {
System.out.println(1);
}
And provide a method:
public void stopThread(){
stopThread.set(true);
}
Alternatively you can use interrupt() and check interrupted(). These are cleaner methods provided in the Thread class. interrupted() has the behaviour of clearing the flag when called. That's not always helpful and while the flag can be examined by Thread.currentThread().isInterrupted() the 'checking the flag clears it' behaviour can be unhelpful and also suffers some of the issues of stop() because it can cause "surprising" exceptions to be throw at points other code has never anticipated. The right approach is to use your own flag and be in full control of where the process decides to quit.
Take your pick.
See also: Java Thread Primitive Deprecation
Ever wondered why when you click 'Cancel' on some concurrent process you are often made to wait ages for it to respond?
This is why. The task needs to come to a well defined point and do any necessary clean up to terminate in a well defined way.
Think of Thread#stop() as like stopping a cyclist by kicking them off their bike. The method here waves a red flag at them and they then come to a halt as swiftly as they safely can.
Thread#stop() should never have been in Java and you should never use it.
You get away with it in development and small systems. It causes havoc in large production environments.
It's not just deprecated as 'not recommended' it is 'inherently unsafe' do not use it.
It's been deprecated for years and its disappointing that some 'removal date' has never been advertised.
Here's an example that uses either Thread#stop() or interrupt() depending on whether you opt for being dangerous.
import java.lang.System;
import java.lang.Thread;
class Ideone
{
private static boolean beDangerous=true;//Indicates if we're going to use the Thread#stop()....
//This main method uses either stop() or interrupt() depending on the option.
public static void main (String[] args) throws java.lang.Exception
{
PrimeFactor factor=new PrimeFactor();
try{
for(int i=1;i<30;++i){
Thread thrd=new Thread(new Primer(factor));
thrd.start();
Thread.sleep(10);//Represents some concurrent processing...
if(beDangerous){
thrd.stop();
}else{
thrd.interrupt();
}
thrd.join();
if(!factor.check()){
System.out.println("Oops at "+i);
}
}
}catch(Throwable t){
System.out.println(t);
}
}
//This class just hammers the PrimeFactor object until interrupt()ed (or stop()ed).
private static class Primer implements Runnable {
private PrimeFactor factor;
public Primer(PrimeFactor ifactor){
factor=ifactor;
}
public void run(){
int i=1;
while(!Thread.interrupted()){
factor.set(i++);
}
}
}
//Don't worry about this bit too much.
//It's a class that does a non-trivial calculation and that's all we need to know.
//"You're not expected to understand this". If you don't get the joke, Google it.
//This class calculates the largest prime factor of some given number.
//Here it represents a class that ensures internal consistency using synchronized.
//But if we use Thread#stop() this apprently thread-safe class will be broken.
private static class PrimeFactor {
private long num;
private long prime;
public static long getFactor(long num){
if(num<=1){
return num;
}
long temp=num;
long factor=2;
for(int i=2;temp!=1;++i){
if(temp%i==0){
factor=i;
do{
temp=temp/i;
}while(temp%i==0);
}
}
return factor;
}
public synchronized void set(long value){
num=value;
prime=getFactor(value);
}
public synchronized boolean check(){
return prime==getFactor(num);
}
}
}
Typical partial output:
Oops at 1
Oops at 2
Oops at 3
Oops at 6
Oops at 8
Notice that the PrimeFactor class can be described as thread-safe. All it's methods are synchronized. Imagine it's in some library. It's unrealistic to expect "thread-safe" to mean Thread#stop()-safe and the only way to do that would be intrusive. Putting calls to it in a try-catch(ThreadDeath tde) block won't fix anything. The damage will have been down before it's caught.
Don't convince yourself that changing set() to the following solves it:
public synchronized void set(long value){
long temp=getFactor(value);
num=value;
prime=temp;
}
First and foremost the the ThreadDeath exception could throw during the assignments so all that does is potentially shorten the odds on the Race Condition. It hasn't been negated. Never make "how likely is that to happen" arguments about race conditions. Programs call methods billions of times so billion to one-shots come up regularly.
To use Thread#stop() you can essentially never use any library objects including java.* and jump through hoops to handle ThreadDeath everywhere in your code and almost certainly eventually fail anyway.
In java there is no official way of killing thread. This is bug. (no need to argue with it here) Thread#stop() should not be deprecated. It may be improved that it cannot be consumed. Even now it will work most of the time just fine.
Right now, if I write function which will be executed with kill need, I would start new thread and joint to it with timeout or other disconnect mechanism. This will make your code to continue like main thread was killed. Problem is that main thread is still running. All resources are still in use. This is still better than application being frozen. Calling thread.interrupt() is first step but it this does not work using thread.stop() is adequate here. It won't make things worse.
If you really must kill the thread, only way would be to start another jvm via jni, run unsafe code there and use linux kill -9 to stop the whole process if needed.
I believe killing thread is perfectly possible, only jvm developers didn't care enough. I get into this situation all the time and answers like don't use any libraries, fix all foreign code, write your own language or live with it are just frustrating.

Multi-threading -- a faster way?

I have a class with a getter getInt() and a setter setInt() on a certain field, say field
Integer Int;
of an object of a class, say SomeClass.
The setInt() here is synchronized-- getInt() isn't.
I am updating the value of Int from within multiple threads.
Each thread is getting the value Int, and setting it appropriately.
The threads aren't sharing any other resources in any way.
The code executed in each thread is as follows.
public void update(SomeClass c) {
while (<condition-1>) // the conditions here and the calculation of
// k below dont have anything to do
// with the members of c
if (<condition-2>) {
// calculate k here
synchronized (c) {
c.setInt(c.getInt()+k);
// System.out.println("in "+this.toString());
}
}
}
The run() method is just invoking the above method on the members updated from within the constructor by the params passed to it:
public void run() { update(c); }
When I run this on large sequences, the threads aren't interleaving much-- i see one thread executing for long without any other thread running in between.
There must be a better way of doing this.
I can't change the internals of SomeClass, or of the class invoking the threads.
How can this be done better?
TIA.
//=====================================
EDIT:
I'm not after manipulating the execution sequence of the threads. They all have the same priority. It`s just that what i see in the outcome is suggesting that the threads aren't sharing the execution time evenly-- one of them, once takes over, executing on. However, I can't see why this code should be doing this.
It`s just that what i see in the outcome is suggesting that the threads aren't sharing the execution time evenly
Well, this is exactly what you don't want if you are after efficiency. Yanking a thread from being executed and scheduling another thread is generally very costly. Therefore it's actually advantageous to do one of them, once takes over, executing on. Of course, when this is overdone you could see higher throughput but longer response time. In theory. In practice, JVMs thread scheduling is well tuned for almost all purposes, and you don't want to try changing it in almost all situations. As a rule of thumb, if you are interested in response times in millisecond order, you probably want to stay away messing with it.
tl;dr: It's not being inefficient, you probably want to leave it as it is.
EDIT:
Having said that, using an AtomicInteger may help in performance, and is in my opinion less error prone than using a lock (synchronized keyword). You need to be hitting that variable really very hard in order to get a measurable benefit though.
The JDK provides a nice solution for multi threaded int access, AtomicInteger:
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicInteger.html
As Enno Shioji has pointed out, letting one thread proceed might be the most efficient way to execute your code in some scenarios.
It depends on how much cost the thread synchronization imposes in relation to the other work of your code (which we don’t know). If you have a loop like:
while (<condition-1>)
if (<condition-2>) {
// calculate k here
synchronized (c) {
c.setInt(c.getInt()+k);
}
}
and the test for condition-1 and condition-2 and the calculation of k is rather cheap compared to the synchronization cost, the Hotspot optimizer might decide to reduce the overhead by transforming the code to something like this:
synchronized (c) {
while (<condition-1>)
if (<condition-2>) {
// calculate k here
c.setInt(c.getInt()+k);
}
}
(or a rather more complicated structure by performing loop unrolling and span the synchronized block over multiple iterations). The bottom line is that the optimized code might block other threads longer but let the one owning the lock finish faster resulting in an overall faster execution.
This does not mean that a single-threaded execution was the fastest way to handle your problem. It also doesn’t mean that using an AtomicInteger here would be the best option to solve the problem. It would create a higher CPU load and possibly a small acceleration but it doesn’t solve your real mistake:
It is completely unnecessary to update c within the loop at a high frequency. After all, your threads do not depend on seeing updates to c timely. It even looks like they are not using it at all. So the correct fix would be to move the update out of the loop:
int kTotal=0;
while (<condition-1>)
if (<condition-2>) {
// calculate k here
kTotal += k;
}
synchronized (c) {
c.setInt(c.getInt()+kTotal);
}
Now, all threads can run in parallel (assuming the code you haven’t posted here doesn’t contain inter-thread dependencies) and the synchronization cost is reduced to a minimum. You could still change it to an AtomicInteger as well but that’s not that important anymore.
Answering to this
i see one thread executing for long without any other thread running in between.
There must be a better way of doing this.
You can not control how threads will be executed. JVM does this for you, and does not like you to interfere in its work.
Still you can look at yield as your option, but that also does not ensure same thread will not be picked again.
The java.lang.Thread.yield() method causes the currently executing thread object to temporarily pause and allow other threads to execute.
I've found it better to use wait() and notify() than yield. Check out this example (seen from a book)-
class Q {
int n;
boolean valueSet = false;
synchronized int get() {
if(!valueSet)
wait(); //handle InterruptedException
//
valueSet = false;
notify();//if thread waiting in put, now notified
}
synchronized void put(int n) {
if(valueSet)
wait(); //handle InterruptedException
//
valueSet = true;
//if thread in get waiting then that is resumed now
notify();
}
}
or you could try using sleep() and join the threads in the end in main() but that isn't a foolproof way
You are having public void update(SomeClass c) method in your code and this method is an instance method in which you are passing the object as parameter.
synchronized(c) in your code is doing nothing. Let me show you with some example,
So if you will make different objects of this class and then try to make them different threads like,
class A extends Thread{
public void update(SomeClass c){}
public void run(){
update(c)
}
public static void main(String args[]){
A t1 = new A();
A t2 = new A();
t1.start();
t2.start();
}
}
Then both of these t1 & t2 will have their own copies of update method and the reference variable c which you are making synchronized will also be different for both the threads. t1 calls its own update() method and t2 calls its own update() method. So synchronization won't work.
Synchronization will work when you have something common for both the threads.
Something like,
class A extends Thread{
static SomeClass c;
public void update(){
synchronized(c){
}
}
public void run(){
update(c)
}
public static void main(String args[]){
A t1 = new A();
A t2 = new A();
t1.start();
t2.start();
}
}
This way the actual concept of synchronization will be applied.

Categories

Resources