1) if synchronized(this) is used, which means that any of the two threads will lock on factor instance and increment val variable value till the loop exits.
so synchronized(this) means here that we should not use any other instance variables. We have to use only the variables of factor instance inside the synchronized block?
2) if synchronized(addition) means here that we have to use only add variable not the val variable of factor instance class?
There is a big confusion regarding this synchronization block .
what i understood is synchronization block will lock on the object's instance and guard the operation and make it thread safe. But using different instance really means that it should guard only that particular instance variables not any other instance variables. Can anyone explain in depth concept regarding this relating with the code provided below
class Factor implements Runnable
{
int val = 0;
Addition addtion = new Addition();
#Override
public void run()
{
currInsLock();
diffInsLock();
}
// locking on the current instance which is this
// we will use synchronized(this)
public void currInsLock()
{
synchronized (this)
{
for(int i=0;i<100;i++)
{
try
{
Thread.sleep(100);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"---val value lock on this obj -->"+val++);
}
}
}
// locking on the different instance
public void diffInsLock()
{
synchronized (addtion)
{
for(int i=0;i<100;i++)
{
try
{
Thread.sleep(100);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"---val value lock on addition obj -->"+val++);
System.out.println(Thread.currentThread().getName()+"---add value lock on addition obj -->"+addtion.add++);
}
}
}
}
Addition class :
public class Addition
{
public int add=0;
}
The Main class
public class ConcurrentDoubt {
public static void main(String[] args)
{
Factor factor=new Factor();
Thread thread1=new Thread(factor);
Thread thread2=new Thread(factor);
thread1.start();
thread2.start();
}
}
What you use as object's monitor is not really important, it could be any object, I would even say that ideally we should never use this as object's monitor but rather a private final Object instance to better protect our class because if outside your code, we use the instance of your class as object's monitor it could prevent your class to work properly.
The key point is to use exact same object's monitor anytime you want to modify or access to anything that you want to protect (member variables, class instances...) if what you want to protect is accessed/modified outside a synchronized block or with a different object's monitor, your code is no more thread-safe because you don't prevent concurrent accesses or modifications anymore. Indeed only one thread can execute code protected by a synchronized block for a given object's monitor, so it you have 2 different object's monitors to protect the same thing, you could have 2 threads accessing/modifying what you try to protect.
So here, you use this and addtion as object's monitors to protect your member variable val so your code is not thread-safe, you need to use the same object's monitor.
Assuming that you want to use this as object's monitor to protect your member variable val, your code should rather be:
synchronized (addtion) {
for(int i=0;i<100;i++) {
...
synchronized (this) {
System.out.println(
Thread.currentThread().getName() +
"---val value lock on addition obj -->" + val++
);
}
System.out.println(
Thread.currentThread().getName() +
"---add value lock on addition obj -->" + addtion.add++
);
}
}
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?
is it possible to change the value of a instance variable from the different class thread After acquiring a lock.
I have a class ThreadTest, it has String test instance variable.
In Run method i have taken a lock on String test instance variable.
if JVM has already taken a lock on instance variable then why im able to change the value it from main thread.
ThreadTest.class
package com;
public class ThreadTest implements Runnable{
String test;
int i=100;
public ThreadTest(String test) {
super();
this.test = test;
}
#Override
public void run() {
// TODO Auto-generated method stub
// Thread.currentThread().dumpStack();
while(i>0)
{
synchronized(test){
System.out.println("Thrad Test Run--- "+test+" - "+i+"- -- "+Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
i--;
}
}
}
Test.class
package com;
public class Test {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
ThreadTest testThread=new ThreadTest("1");
Thread thread=new Thread(testThread);
thread.setName("First Thread");
Thread thread1=new Thread(testThread);
thread1.setName("Second Thread");
thread.start();
thread1.start();
int i=100;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while(true)
{
//here im accessing the 'test' that is instance variable of ThreadTest.
// and First Thread alredy acquired a lock on 'test'.
//so according to the JAVA threading testThread.test=10 is not valid.
//how multiple threads are able to change the value of testThread.test
testThread.test="10";
//System.out.println("main thread...");
}
}
}
There appears to be confusion about what the synchronized statement does.
synchronized does not lock an instance variable, it 'locks' an object. (Actually, 'lock' isn't the word used here. It acquires the object's 'monitor'.) When a synchronized statement is used (as above), the provided expression is evaluated to determine which object's monitor to acquire. For example, here are valid, though probably nonsensical, synchronized statements:
synchronized ("1") {
// ...
}
synchronized (new Object()) {
// ...
}
The first acquires the monitor on the String object representing the string literal "1". The second acquires the monitor on a brand new object (which is never useful for managing concurrency).
synchronized is for marking a critical section in a program. A critical section is a block of code that must not be executed concurrently. See Critical Section on Wikipedia
In regards to the code above, synchronized does not prevent reads or writes of instance (or class) variables.
The following might be helpful: Synchronization from the Java Tutorial
Is it possible to ... after acquiring a lock.
If thread A acquires a lock, that does not limit the ability of thread A to do anything in any way whatsoever.
If thread A acquires a lock, it limits the ability of thread B to do exactly one thing: It prevents thread B from acquiring the same lock until thread A has released it. It does not prevent thread B from doing anything else. In particular, it does not prevent thread B from accessing or modifying the object that is "locked".
Is it possible to change the value of a instance variable...
Yes, if the variable is not final.
...from the different class
Whether or not a method in class A can refer directly to a variable declared in class B depends on the access level (private, protected, public, or default) that is specified in the variable's declaration. https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
The use of synchronized blocks and the use of threads do not change the meaning of access levels in any way.
Of course, a method in class A may also be able to indirectly affect even a private variable in class B by calling some method of class B.
...from the different ... thread
If a method in class A can directly or indirectly affect a variable declared in class B, then it does not matter what thread is executing the method. All threads see the same heap.
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
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);
}
}
}
How can I prevent from concurrent access. I have code like this
public class MC implements Runnable {
public void run() {
sync();
}
public static void main(String p[]){
MC mc = new MC();
MC mc2 = new MC();
MC mc3 = new MC();
MC mc4 = new MC();
Thread t = new Thread(mc);
t.start();
Thread t2 = new Thread(mc2);
t2.start();
Thread t3 = new Thread(mc3);
t3.start();
Thread t4 = new Thread(mc4);
t4.start();
}
private synchronized void sync(){
try {
System.out.println(System.currentTimeMillis());
Thread.sleep(10000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
and I am getting output like this
1307082622317
1307082622317
1307082622317
1307082622317
BUILD SUCCESSFUL (total time: 11 seconds)
any advice?
make your method static:
private static synchronized void sync();
your method as coded is synchronized on the instance, but each thread has its own instance, so there's no synchronization.
static methods are synchronized on the Class object, of which there is only one per class, so all instances will synchronize on static methods.
You've got four separate MC objects. Typically running an instance method on those (sync), they shouldn't interfere with each other. You can use a synchronized block to make sure only one runs at a time, but you need to consider what to synchronize on:
If you synchronize on a separate object per instance, that would stop two threads from running the code for the same object. That's effectively what you've got now, but you're implicitly synchronizing on this, which I would discourage you from doing. (Any other code could synchronize on the same object.)
If you synchronize on an object that all the instances know about (e.g. via a static variable) then that would only let one thread run the code at all.
It sounds like you want the latter approach, but it doesn't sound like great design to me. If you really want to implement it that way, you'd use:
public class MC implements Runnable {
private static readonly Object lock = new Object();
...
private void sync() {
synchronized (lock) {
try {
System.out.println(System.currentTimeMillis());
Thread.sleep(10000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
}
Keeping sync as a synchronized method but making it static would also work, but again you'd be locking on a publicly visible object (MC.class) which I generally discourage.
For the desired functionality, you can make the sync function static. I don't talk about the goodness of design. It just do it the way you like!
private static synchronized void sync()
You are instantiating four objects, and sychronized is on different monitor. Either make sync static so that the actual class will be the monitor, or when you instantiate, pass same monitor object to all four, then sync on it
use a static lock tisynchronize your method. lock classes are inside the java.concurent package
Hi u are creating new instances of ur class MC, synchronized method guarantees single access for one instance if it is not static method.
I would suggest u have a private static variable say Integer lock, and then synchronize on it:
private void sync()
{
synchronized (lock)
{
try {
System.out.println(System.currentTimeMillis());
Thread.sleep(10000);
} catch (InterruptedException ex){
ex.printStackTrace();
}
}
}