Why is Java synchronized not working as expected? - java

I'm trying to figure out how synchronized methods work. From my understanding I created two threads T1 and T2 that will call the same method addNew, since the method is synchronized shouldn't it execute all the iterations of the for loop for one thread and then the other? The output keeps varying, sometimes it prints it right, other times it prints values from T1 mixed with T2 values. The code is very simple, can someone point out what am I doing wrong? Thank you.
public class Main {
public static void main(String[] args) {
Thread t1 = new Thread(new A());
Thread t2 = new Thread(new A());
t1.setName("T1");
t2.setName("T2");
t1.start();
t2.start();
}
}
public class B {
public synchronized void addNew(int i){
Thread t = Thread.currentThread();
for (int j = 0; j < 5; j++) {
System.out.println(t.getName() +"-"+(j+i));
}
}
}
public class A extends Thread {
private B b1 = new B();
#Override
public void run() {
b1.addNew(100);
}
}

Each A instance has its own B instance. The method addNew is an instance method of B. Therefore, the lock acquired implicitly during calls to addNew is the lock on the receiver B instance. Each thread is calling addNew on a different B, and therefore locking on different locks.
If you want all B instances to use a common lock, create a single shared lock, and acquire it in the body of addNew.

Both A objects have their own B object. You need them to share a B so the synchronization can have an effect.

try this :
public class Main {
public static void main(String[] args) {
A a = new A();
Thread t1 = new Thread(a);
Thread t2 = new Thread(a);
t1.setName("T1");
t2.setName("T2");
t1.start();
t2.start();
}
}
class B {
public synchronized void addNew(int i){
Thread t = Thread.currentThread();
for (int j = 0; j < 5; j++) {
System.out.println(t.getName() +"-"+(j+i));
}
}
}
class A extends Thread {
private B b1 = new B();
#Override
public void run() {
b1.addNew(100);
}
}

Related

How to execute three thread simultaneously?

This is my code which i tried but my main class is not there because i don't know how to use that one
//first thread
class firstthread extends Thread
{
public void run(){
for(int i=0;i<1000;i++)
{
System.out.println(i);
}}
}
//second thread
class secondthread extends Thread
{
public void run(){
for(int i=0;i<1000;i++)
{
System.out.println(i);
}}
}
First overide the run method and then create the object of thread class in main()
and call start method.
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
new Thread() {
public void run() {
for(int y=0;y<1000;y++)
{
System.out.println(y);
}
};
}.start();
}
}
Whatever you have written is incomplete code, to create a thread you need to extend Thread class or implement Runnable interface and then override its public void run() method.
To create a thread you need to override the method public void run
Then to start the threads you need to call its start() method.
A simple complete example
class MyThread extends Thread {
String name;
public void run(){
for(int i=0;i<1000;i++) {
System.out.println("Thread name :: "+name+" : "i);
}
}
}
class Main{
public static void main(String args[]){
MyThread t1 = new MyThread();
t1.name = "Thread ONE";
MyThread t2 = new MyThread();
t2.name = "Thread TWO";
MyThread t3 = new MyThread();
t3.name = "Thread THREE";
t1.start();
t2.start();
t3.start();
}
}
You can't just put some code in your class body.
You need a method to have the code in, the method being run() in case of thread.
Instead of copy-pasting the code, I'll point you to the official documentation where you can find some examples.
Sample program given below. Since there is no synchronization code, there output is mixed from the three threads
public class ThreadTest implements Runnable{
#Override
public void run() {
System.out.print(Thread.currentThread().getId() + ": ");
for(int i=0;i<100;i++)
System.out.print(i + ", ");
System.out.println();
}
public static void main(String[] args) {
for(int i=0;i<3;i++){
new Thread(new ThreadTest()).start();
}
}
}

Synchronized two threads not working synchronized

consider the following code:
public class Main {
public static void main(String[] args){
MyObject obj = new MyObject();
Thread1 t1 = new Thread1(100,'#',obj);
Thread1 t2 = new Thread1(100,'*',obj);
t1.start();
t2.start();
}
}
public class Thread1 extends Thread {
int myNum;
char myChar;
MyObject myObj;
public Thread1(int num, char c, MyObject obj){
myNum = num;
myChar = c;
myObj = obj;
}
public synchronized void run(){
for(int i = 1; i<myNum; i++){
if((i%10)==0)
System.out.println("");
System.out.print(myChar);
}
}
}
The class MyObject is empty class without anything spacial.
My question is, why the synchronized is not working and I get printed the '#' and '' simultaneously and in random order and not one after the other?
Synchronization locks the monitor of an object. In your case, you are synchronizing against each of the threads objects, that is Thread A locks against Threads A's monitor and Thread B locks against Thread B's monitor. Thus they are not interacting.
I think that you meant the following for the run() method:
public void run(){
synchronized (myObj) {
for(int i = 1; i<myNum; i++){
if((i%10)==0)
System.out.println("");
System.out.print(myChar);
}
}
}
If that was indeed your intended use for myObj, then I would suggest the following change too; as it will help make the code more readable.
Change:
MyObject myObj;
to:
private final MyObject lock;
EDIT an alternative approach, that does not lock against myObj but instead the Thread1's instance of Class.
public void run(){
doJob();
}
private static synchronized void doJob() {
for(int i = 1; i<myNum; i++){
if((i%10)==0)
System.out.println("");
System.out.print(myChar);
}
}
You can try to put thread.join(), wait for first thread in execution finished to start next one
public class hilos {
public static void main(String[] args) throws InterruptedException{
MyObject obj = new MyObject();
Thread1 t1 = new Thread1(50,'#',obj);
Thread1 t2 = new Thread1(50,'*',obj);
Thread[] threads = {t1, t2};
start(threads);
}
public synchronized static void start(Thread[] threads) throws InterruptedException{
synchronized(threads){
for(int i=0; i < threads.length; i++) {
threads[i].start();
threads[i].join();
}
}
}
}
OUTPUT:
#########
##########
##########
##########
##########*********
**********
**********
**********
**********

Locking on static object

There are multiple instance of Class A that runs at a time.
Class A calls multiple instances of Class B in its run.
public Class Main {
public static void main(String args[] ) {
A a1 = new A();
Thread t1 = new Thread(a1);
t1.start();
A a2 = new A();
Thread t2 = new Thread(a2);
t2.start();
}
}
Class A implements Runnable {
public void run() {
B b1 = new B();
Thread t11 = new Thread(b1);
t11.start();
B b2 = new B();
Thread t21 = new Thread(b2);
t21.start();
}
}
There is method named "method" in class B where a Set Collection is edited. That edit is done based on static lock in Class B.
EDIT-
Class B implements Runnable {
private final static Object LOCK = new Object();
private final static Set<T> busyRecords = new HashSet<T>();
public void waitToWorkOn(final T obj) {
synchronized(LOCK) {
while (busyRecords.contains(obj)) {
LOCK.wait(); //go to sleep
}
busyRecords.add(obj);
}
}
public void doneWith(final T obj) {
synchronized(LOCK) {
busyRecords.remove(obj);
LOCK.notifyAll();
}
}
public void mathod(obj) {
try{
waitToWorkOn(obj);
.. do some work with obj
}
finally {
doneWith(obj);
}
}
public void run() {
method(getObj())
}
}
But that Set does not need concurrency control when it is accessed from different "A" instances. Only within an A instance, it needs to be locked for all B instances.
By this I mean, that when 2 instances of A are running, they should not be made to wait. But within an A instance if 2 B objects pick same obj, they have to wait inside LOCK.wait.
I don't think that LOCK can be made non-static as A calls multiple instances of B.Can we tune LOCK object here for better concurrency across A objects.
You can create a thread-safe instance of the shared collection and pass it to all the Bs for a given A.
Class A implements Runnable {
public void run() {
// create shared set instance scoped to A, and make it thread-safe
Set col = Collections.synchronizedSet(new HashSet());
B b1 = new B(col);
Thread t11 = new Thread(b1);
t11.start();
B b2 = new B(col);
Thread t21 = new Thread(b2);
t21.start();
}
}
Class B implements Runnable {
private final Set<T> someSet;
private B(Set<T> someSet) {
this.someSet = someSet;
}
public void method(final T obj) {
someSet.add(obj);
}
public void run() {
method()
}
}

How can this code cause deadlock?

While passing SCJP6 exam simulator I found question like this:
class Clerk implements Runnable {
private Record A, B;
public Clerk(Record a, Record b) {
A = a;
B = b;
}
public void run() {
while(true) {
doStuff(A, B);
}
}
public synchronized void doStuff(Record a, Record b) {
synchronized(a) {
synchronized(b) {
a.add(1);
b.add(-1);
}}
}
}
then
Record a = new Record();
Record b = new Record();
new Thread(new Clerk(a, b)).start();
new Thread(new Clerk(a, b)).start();
Answer says that this code can cause deadlock, but I don't get it - how exactly is that possible? Can someone can help me figure that out?
Apart from the fact that it does not compile, there is no deadlock in that code. This code could definitely create a deadlock:
new Thread(new Clerk(a, b)).start();
new Thread(new Clerk(b, a)).start();
So if the question is: could the Clerk class be the source of the deadlock? Then the answer is yes.
EDIT
Short example that should deadlock fairly fast. If a and b are used like in the original question, the program runs fine.
public class Test1 {
public static void main(String[] args) {
Record a = new Record();
Record b = new Record();
new Thread(new Clerk(a, b)).start();
new Thread(new Clerk(b, a)).start();
}
static class Record {
}
static class Clerk implements Runnable {
private Record A, B;
public Clerk(Record a, Record b) {
A = a;
B = b;
}
public void run() {
while (true) {
System.out.println("in thread " + Thread.currentThread());
for (int i = 0; i < 10000; i++) {
doStuff(A, B);
}
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
}
}
}
public synchronized void doStuff(Record a, Record b) {
synchronized (a) {
synchronized (b) {
}
}
}
}
}
I would expect this to deadlock if one thread was constructed with a/b, and the second with b/a.
In this situation a thread would put a lock on the first entity and the then on the second. If thread 1 locked a and tried to lock b, and thread simultaneously 2 locked b and waited for a, then it would all grind to a halt.
Here's the Java tutorial deadlock example, which is very similar to the above example.

Java Threads - Synchronized(this)

Please see the program below
public class TestVolatile implements Runnable {
public static volatile int counter;
public static String lock = "lock";
public static void main(String[] args) {
Thread t1 = new Thread(new TestVolatile(),"Thread-1");
Thread t2 = new Thread(new TestVolatile(),"Thread-2");
t1.start();
t2.start();
}
public void run() {
synchronized(this) {
System.out.println(Thread.currentThread()+"-"+counter);
counter++;
}
}
}
If I run this program multiple times, I get 3 different results.
first is
Thread[Thread-1,5,main]-0
Thread[Thread-2,5,main]-0
second is
Thread[Thread-1,5,main]-0
Thread[Thread-2,5,main]-1
third is
Thread[Thread-1,5,main]-1
Thread[Thread-2,5,main]-0
But if change the lock object from "this" to "lock", I get 2 different results
first is
Thread[Thread-1,5,main]-0
Thread[Thread-2,5,main]-1
second is
Thread[Thread-1,5,main]-1
Thread[Thread-2,5,main]-0
My assumption when writing the program was that in either case the "counter" should never come 0 in both statements.
Can somebody explain?
You create two TestVolatile objects. The "this" keyword refers to the TestVolatile object being run in the thread. Thus you do not synchronize on the same object in the first example.
If you change the code like this, then the first example starts working:
public static void main(String[] args) {
TestVolatile testVolatile = new TestVolatile();
Thread t1 = new Thread(testVolatile,"Thread-1");
Thread t2 = new Thread(testVolatile,"Thread-2");
t1.start();
t2.start();
}
It's probably not what you're looking for, but if you want to avoid the use of synchronized and volatile, you should use an instance of AtomicInteger:
http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/atomic/AtomicInteger.html
Use the getAndIncrement method to show the same behavior as in your example.
public class TestVolatile implements Runnable {
public static AtomicInteger counter = new AtomicInteger();
public static void main(String[] args) {
Thread t1 = new Thread(new TestVolatile(),"Thread-1");
Thread t2 = new Thread(new TestVolatile(),"Thread-2");
t1.start();
t2.start();
}
public void run() {
System.out.println(Thread.currentThread() + " - " + counter.getAndIncrement());
}
}

Categories

Resources