The lock on an object by one thread, no other thread can enter any of the synchronized methods in that class ,but i want to know about non-synchronized method can access by other thread,,,,,,,
class Account {
private int balance = 50;
public int getBalance() {
return balance;
}
public void withdraw(int amount) {
balance = balance - amount;
}
}
public class AccountDanger implements Runnable {
private Account acct = new Account();
public void run() {
for (int x = 0; x < 5; x++) {
this. d();
makeWithdrawal(10);
if (acct.getBalance() < 0) {
System.out.println("account is overdrawn!");
}
}
}
private synchronized void makeWithdrawal(int amt) {
if (acct.getBalance() >= amt) {
System.out.println(Thread.currentThread().getName()
+ " is going to withdraw"+amt);
try {
Thread.sleep(500);
// Thread.sleep(500);
} catch (InterruptedException ex) {
}
acct.withdraw(amt);
System.out.println(Thread.currentThread().getName()
+ " completes the withdrawal"+acct.getBalance());
} else {
System.out.println("Not enough in account for " + Thread.currentThread().getName()
+ " to withdraw " + acct.getBalance());
}
}
public static void main(String[] args) {
AccountDanger r = new AccountDanger();
Thread one = new Thread(r);
Thread two = new Thread(r);
one.setName("Fred");
two.setName("Lucy");
one.start();
two.start();
}
private void d() {
System.out.println("hhhhhhhhhhhhhhhhhhhhh"+Thread.currentThread().getName());
}
}
You have answer in your question itself :). If you are just looking for confirmation : YES.
No lock is required to access non-synchronized methods of an object.
If you want to know more about these concepts, visit Object Locks
Yes, the unsynchronized methods can be accessed/called by any Thread, that has/gets the reference to the same instance. Since you created a private Account instance and you didn't give this instance to any other class, in your example no other thread is able to access this special instance.
Related
public class driver{
public static void main(String[] args) {
PrintNum firstObjectForThread = new PrintNum(0); // the argument is not used, ignore it
firstObjectForThread.startNewThread();
PrintNum secondObjectForThread = new PrintNum(0);
secondObjectForThread.startNewThread();
}
This is the class that the driver calls:
public class ClassName implements Runnable{
int variableForUpdate;
private Thread t;
private static ArrayList<Integer> intArray;
public ClassName(int variableForUpdate) {
super();
this.intArray = new ArrayList<Integer>();
this.variableForUpdate = variableForUpdate;
for (int i = 0; i < 30 ; i++) {
this.intArray.add(i);
}
}
#Override
public void run() {
runThisWhenThreadStarts();
}
private synchronized void runThisWhenThreadStarts() {
System.out.println("Started");
for (int i = 0; i < 30; i++) {
System.out.println(intArray.get(i));
}
}
public void startNewThread() {
t = new Thread(this);
t.start();
}
}
If I use block synchronization the following, the output is synchronized:
private void runThisWhenThreadStarts() {
synchronized (ClassName.class) {
System.out.println("Started");
for (int i = 0; i < 30; i++) {
System.out.println(intArray.get(i));
}
}
}
I have been troubleshooting this for many hours and cannot figure out... Can anyone shed some light please?
I also notice if I use the same object to call startNewThread(), the synchronization will work. But I don't understand why.
PrintNum firstObjectForThread = new PrintNum(0); // the argument is not used, ignore it
firstObjectForThread.startNewThread();
firstObjectForThread.startNewThread();
I want to use two different object from the same class instead of one object calling the method twice (the workaround above).
I am able to use the synchronized methods in another program, with 2 different instances (get and put) :
public class Hello extends Thread {
int x;
Coffee x1;
int threadno;
Hello(int x, Coffee x1) {
this.x = x;
threadno = x;
this.x1 = x1;
}
public void run() {
switch (x) {
case 0:
System.out.println("Start thread " + threadno + " Get");
break;
case 1:
System.out.println("Start thread " + threadno + " Put");
break;
}
ops();
System.out.println("Stopping thread " + threadno);
}
public void ops() {
x1.get();
}
public static void main(String[] args) {
Coffee c1 = new Coffee();
Hello get = new Hello(0, c1);
Hello put = new Hello(0, c1);
get.start();
put.start();
}
}
Hello class will call coffee class:
class Coffee {
boolean available = false; // indicating there nothing to get.
// waiting on each other.
int contents = 55;
public synchronized int get() {
System.out.println("Entering Get method " + contents);
for (int i = 0; i < 30; i++) {
System.out.println(i);
}
return contents;
}
}
In the first example, the method acquires the lock on the object instance that the method is called on. The block doesnt do that, instead it acquires the lock on the class.
Taking the lock on the instance has no effect on the other thread, it is a different object. Both threads are acquiring their own lock, which is useless. Neither thread is prevented from doing anything.
Taking the lock on the class means both threads are trying to acquire the same lock. For locking to work the same lock has to be used by both threads.
In the second example the Coffee object is shared by both threads, and both threads are trying to acquire the same lock on the Coffee object. That means the second thread to get to the lock has to block until the lock is released by the first thread, locking successfully keeps the thread out until the first thread is done.
To understand synchronized, keep track of what locks are being acquired.
I'm reading Thinking in JAVA (Ed4, by Bruce Eckel), which says:
Note that it’s especially important to make fields private when
working with concurrency; otherwise the synchronized keyword cannot
prevent another task from accessing a field directly, and thus
producing collisions.
I am confused and finally get this demo:
public class SimpleSerial {
public static void main(String[] args) throws IOException {
ShareObject so = new ShareObject();
Thread thread1 = new Thread(new ThreadOperation(so, "add"));
Thread thread2 = new Thread(new ThreadOperation(so, "sub"));
thread1.setDaemon(true);
thread2.setDaemon(true);
thread1.start();
thread2.start();
System.out.println("Press Enter to stop");
System.in.read();
System.out.println("Now, a=" + so.a + " b=" + so.b);
}
}
class ThreadOperation implements Runnable {
private String operation;
private ShareObject so;
public ThreadOperation(ShareObject so, String oper) {
this.operation = oper;
this.so = so;
}
public void run() {
while (true) {
if (operation.equals("add")) {
so.add();
} else {
so.sub();
}
}
}
}
class ShareObject {
int a = 100;
int b = 100;
public synchronized void add() {
++a;
++b;
}
public synchronized void sub() {
--a;
--b;
}
}
Every time the values of a and b are different. So why?
The demo also mentioned if the thread sleep() for short time, i.e., re-write the run() method in ThreadOperation:
public void run() {
while (true) {
if (operation.equals("add")) {
so.add();
} else {
so.sub();
}
try {
TimeUnit.MILLISECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
then values of a and b are the same.
So again, Why? What happens behind sleep()?
With sleep() it becomes probable that the println() executes while the threads are sleeping. The program is still very not thread-safe.
You could fix it by adding a synchronized print() method to SharedObject eg:
public synchronized void print() {
System.out.println("Now, a=" + a + " b=" + b);
}
and calling that on the last line of main instead of the current unsynchronized accesses.
I wrote a simple program to learn about synchronized block. The program is as follow:
public class SychronizedBlock {
static int balance = 0;
static Integer lock = 0;
public static void deposit(int amt) {
Thread t1 = new Thread(new Runnable() {
public void run() {
acquire_lock();
int holdings = balance;
balance = holdings + amt;
System.out.println("deposit " + amt + ", balance: " + balance);
release_lock();
}
});
t1.start();
}
public static void acquire_lock() {
synchronized(lock) {
while (lock == 1) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
lock = 1;
}
}
public static void release_lock() {
synchronized(lock) {
lock = 0;
lock.notifyAll();
}
}
public static void test1() {
balance = 0;
deposit(500);
deposit(500);
}
public static void main(String[] args) {
test1();
}
}
However, when running the program, I met with an IllegalMonitorStateException. I think I have place the wait() and notifyAll() function in the synchronized block, and I have set the lock as parameter of synchronized. Why do I still have Exception?
Problem is with your release_lock method. You are reassigning lock to 0 before calling lock.notifyAll(). Which means the notifyAll will be called on a new Integer object which is not locked. Change the code to following to fix the issue.
public static void release_lock() {
synchronized(lock) {
lock.notifyAll();
lock = 0;
}
}
I'm new to using wait() and notify() in Java and I'm getting an IllegalMonitorStateException.
Main Code
public class ThreadTest {
private static Integer state = 0;
public static void main(String[] args) {
synchronized(state) {
System.out.println("Starting thread");
Thread t = new Thread(new AnotherTest());
t.start();
synchronized(state) {
state = 0;
while(state == 0) {
try {
state.wait(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("State is: " + state);
}
}
}
public static class AnotherTest implements Runnable {
#Override
public void run() {
synchronized(state) {
state = 1;
state.notify();
}
}
}
}
I'm getting an IllegalMonitorStateException what state.notify() is called. Any ideas?
Edit: Based on answer below here is code that works. As a side note, I was first trying this with an enum which has the same problem of using Integer.
public class ThreadTest {
private static int state = 0;
private static Object monitor = new Object();
public static void main(String[] args) {
synchronized(monitor) {
System.out.println("Starting thread");
Thread t = new Thread(new AnotherTest());
t.start();
state = 0;
while(state == 0) {
try {
for(int i = 0; i < 5; i++) {
System.out.println("Waiting " + (5 - i) + " Seconds");
Thread.sleep(1000);
}
monitor.wait(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("State is: " + state);
}
}
public static class AnotherTest implements Runnable {
#Override
public void run() {
synchronized(monitor) {
state = 1;
monitor.notify();
}
}
}
}
This
private static Integer state = 0;
is equivalent to
private static Integer state = Integer.valueOf(0);
The invocation of valueOf(0) returns a reference to an Integer object, call it A.
You then do
synchronized(state) {
your thread acquires the lock on the object referenced by state, currently that is A.
You then do
state = 1;
which is equivalent to
state = Integer.valueOf(1);
which gives you a different reference to an Integer object, call it B, and assigns it to state. When you then call
state.notify();
you're invoking notify() on an object, B, for which your thread doesn't own the monitor. You can't call notify or wait on objects for which your thread doesn't own the monitor.
I am looking at an example which code is:
class SimpleThread extends Thread {
public SimpleThread(String str) {
super(str);
}
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(i + " " + getName());
try {
sleep((int)(Math.random() * 1000));
} catch (InterruptedException e) {}
}
System.out.println("DONE! " + getName());
}
}
and
class TwoThreadsTest {
public static void main (String args[]) {
new SimpleThread("Jamaica").start();
new SimpleThread("Fiji").start();
}
}
My question is: is there a way each thread does its own code? For example, one thread increments a variable, while the other thread increments other variable.
Thanks.
P.S. Example's link is: http://www.cs.nccu.edu.tw/~linw/javadoc/tutorial/java/threads/simple.html
Each instance of SimpleThread has it's own local class storage. As long as you aren't using fields marked as static, then each thread will "do its own code". It is much harder to synchronize values between threads.
For example:
class SimpleThread extends Thread {
// this is local to an _instance_ of SimpleThread
private long sleepTotal;
public SimpleThread(String str) {
super(str);
}
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(i + " " + getName());
try {
long toSleep = Math.random() * 1000;
// add it to our per-thread local total
sleepTotal += toSleep;
sleep(toSleep);
} catch (InterruptedException e) {}
}
System.out.println("DONE! " + getName());
}
}
Im new to Java and threads myself but you can do something like this (which may not be very efficient) but using an if statement to check the id or getName() of the thread and if it .equals the name of the particular thread then do this etc
so something like this:
int i;
int j;
if ("thread 2".equals(Thread.currentThread().getName())){
i++;
System.out.println("this is thread 2");
}
else {
j++;
...
}
This should allow you to make the threads run different tasks under the same run() method