Unable to understand sync - java

Hey I am trying to make 10 threads in a synchronized manner and I came up with the code below however I am not able to understand a part of it as mentioned below. I am still really new to java, I tried looking up synchronized threading from
Here but still I am clueless.
class question3 {
public static void main(String arg[]) throws Exception {
for (int i = 0; i < 11; i++) {
data di = new data();
System.out.println(di.count);
}
}
}
class item {
static int count = 0;
}
class data extends item implements Runnable {
item d = this;
Thread t;
data() {
t = new Thread(this);
t.start();
}
public void run() {
d = syn.increment(d);
}
}
class syn {
synchronized static item increment(item i) {
i.count++;
return (i);
}
}
I am not sure what this part of code does?
public void run() {
d = syn.increment(d);
}
}
class syn {
synchronized static item increment(item i) {
i.count++;
return (i);
}
}

the run function is used when starting the thread, this is a must function you need to override when implement Runnable. When calling Thread.start(), the run function will be called.
The class syn contains a synchronized method, it is simply mean that only one thread can access it each time, thus make the incerment function thread safe.
object d has a static variable count meaning all instances of item class (and data ) share the same count, so all threads increment the same variable
the line d = syn.increment(d); is basically count++ but in a thread safe way

Related

List populated in different thread appears empty in caller thread - Java

My code basically goes like this:
//in Main Thread: (myList is a volatile field)
myList = new ArrayList<myClass>();
Thread myThread = new Thread(new MyCustomRunnable(myList));
myThread.start();
//some lines of code NOT involving myList
myThread.join();
//myList appears empty here even though I can see that the list has been populated
//in the other thread
Is there a reason for this behavior? Like I said, i can see in the debugger that the list has been populated in the called thread, but these changes don't appear in the caller thread after the join() method. MyCustomRunnable also declares the ArrayList as a volatile field, assigned by the constructor.
UPDATE:
Ok, I made a simpler program, replacing the ArrayList with a simple Integer and the results are the same...
public class Threading {
private volatile static Integer i = 0;
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(new MyCustomRunnable(i));
t.start();
t.join();
System.out.println(i); //prints '0', I expected '1'
}
}
public class MyCustomRunnable implements Runnable {
private volatile Integer i;
public MyCustomRunnable(Integer i) {
this.i = i;
}
public void run() {
this.i = 1;
}
}
Why isn't the Integer's value updated in the main Thread?
Add
public static void setI(int i) {
Threading.i = i;
}
to your Threading class and in your runnable add
public void run() {
this.i = 1;
Threading.setI(1);
}
This has nothing to do with multithreading, just variable scoping. i in the Threading class is not updated in MyCustomRunnable's run method.

Mutithreading Synchronization

Synchronization works well with the below code.
public class Main implements Runnable {
public static void main(String[] args) {
Main m = new Main();
for (int i = 0; i < 2; i++) {
Thread t = new Thread(m);
t.start();
}
}
#Override
public void run() {
synchronized(this) {
for (int i = 0; i < 500; i++) {
System.out.println(i);
}
}
}
}
// Synchronization isn't working here.
public class Main implements Runnable {
public static void main(String[] args) {
for (int i = 0; i < 2; i++) {
Thread t = new Thread(new Main());
t.start();
}
}
#Override
public void run() {
synchronized(this) {
for (int i = 0; i < 500; i++) {
System.out.println(i);
}
}
}
}
This question was asked in an interview. I was a bit confused about this so I'm trying to understand why synchronization isn't working with the second code snippet. Can anybody explain me why synchronization won't work with the second code snippet ?
Because synchronization is applied for if you are working on single object.
In first case you have single runnable object of Main i.e. m
In second case you have independent objects of Main.
for(int i=0;i<2;i++){
Thread t = new Thread(new Main()); // independent objects for each thread
t.start();
}
Explaination:
If you see the code you will find below line
synchronized (this) {
this refers to the object itself. So lock is applied based on this object. So in case of multiple Main class object they work independently where as in single object synchronization is applied for that object only.
For more information refer : Intrinsic Locks and Synchronization
Code from the documentation
public class MsLunch {
private long c1 = 0;
private long c2 = 0;
private Object lock1 = new Object();
private Object lock2 = new Object();
public void inc1() {
synchronized(lock1) { // lock is acquired using lock1 object
c1++;
}
}
public void inc2() {
synchronized(lock2) { // lock is acquired using lock1 object
c2++;
}
}
}
In this example you can call both the methods inc1() and inc2() using single object at same time because lock is acquired on different objects. This will help you understand it better.
So in your case lock is acquired on this(object itself). So whenever you have multiple object then it will work independently and when you have single object then it will work synchronously.
You are creating two objects here.
synchronized(this) block will synchronize access to the same object if multiple threads try to access it.
synchronized (this)
"this" is the current object instance. In the first example, instance of Main class is created before invoking the thread and same instance is used. Therefore synchronization works.
But in the second example, in each iteration of the loop in main(), new instance of Main is created. synchronized(this) will not work because there are multiple instances of Main class.
in Java syncronized(object) is effectively using object as an exclusive lock for the code block within syncronized. It may be more obvious why the second version doesn't work if we make the lock explicit, and observe how many instances of the lock get created in each case:
public class Lock {
}
public class Main(Lock lock) implements Runnable {
public static void main(String[] args) {
correct()
incorrect()
}
public static void incorrect() {
for (int i = 0; i < 2; i++) {
//New lock created each iteration
Main m = new Main(new Lock())
Thread t = new Thread(m);
t.start();
}
}
public static void correct() {
//One lock used for all iterations
Main m = new Main(new Lock())
for (int i = 0; i < 2; i++) {
Thread t = new Thread(m);
t.start();
}
}
#Override
public void run() {
synchronized(lock) {
for (int i = 0; i < 500; i++) {
System.out.println(i);
}
}
}
}
// Synchronization isn't working here.
public class Main implements Runnable {
public static void main(String[] args) {
for (int i = 0; i < 2; i++) {
Thread t = new Thread(new Main());
t.start();
}
}
#Override
public void run() {
synchronized(this) {
for (int i = 0; i < 500; i++) {
System.out.println(i);
}
}
}
}
In above example there are 3 threads and 3 Main objects, each thread is taking a lock on different Main object so synchronization will not work.For synchronization to work we should have all threads to take a lock on the single object. Here 3 threads are not taking the lock on a single object but 3 different objects. Each thread is taking a lock on each main object which is not shared among threads. In Thread t = new Thread(m); all threads take a lock on single Main(m) object.
I would have answered that question with a question of my own:
What do you mean, it doesn't work?
The first example serializes the System.out.println() calls and, for the reasons given in several of the other answers here, the second example doesn't serialize the calls, but so what?
System.out is a java.io.PrintWriter, and PrintWriter is inherently thread-safe. Neither of the two examples needs synchronization at all.

Identifying the threads accessing a static block of code?

I have a static function like:
public static void foo()
{
//code follows
System.out.println(Thread.currentThread().getName());
//code follows
}
and multiple threads are calling this function concurrently. I have set the names of threads using
Thread.setName(String)
When i execute the code, the print statement will print the name of only one thread. How can i identify the names of all the threads currently executing the foo() function?
EDIT:
public class FooThread extends Thread
{
public FooThread(String name)
{
this.setName(name);
}
#Override public void run()
{
//do something
//do something
Main.foo();
}
}
//Main Class
public class Main
{
public static void main(String[] args)
{
for(int i=0;i<6;++i)
{
new FooThread("Thread"+i).start();
}
}
public static void foo()
{
//do something
while(true)
{
//do something
System.out.println(Thread.currentThread().getName());
}
}
}
You're already showing the name of the Thread that is calling your code. Code that proves this:
public class Foo2 {
public static synchronized void foo() {
System.out.println(Thread.currentThread().getName());
}
public static void main(String[] args) {
int maxCount = 10;
for (int i = 0; i < maxCount; i++) {
Thread thread = new Thread(new Runnable() {
public void run() {
foo();
}
});
thread.setName("Thread " + i);
thread.start();
long sleepTime = 1000;;
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {}
}
}
}
Return:
Thread 0
Thread 1
Thread 2
Thread 3
Thread 4
Thread 5
Thread 6
Thread 7
Thread 8
Thread 9
Your problem lies in code not shown.
Either your method is being called by one and only one thread, or
Or you're giving all your threads the same name.
Again, for a complete solution as to what is actually wrong with your current set up, create and post an sscce similar to what I've posted above. For all we know you could be calling run() on your Threads, and until we can see and reproduce your problem, I don't think that we'll be able to fully understand it.
EDIT
Regarding your SSCCE: Compare the results of the two methods below, foo1() and foo2()
class FooThread extends Thread {
public FooThread(String name) {
this.setName(name);
}
#Override
public void run() {
// do something
// do something
Main.foo1(); // !! Swap comments
// Main.foo2(); // !! Swap comments
}
}
// Main Class
public class Main {
private static final long SLEEP_TIME = 4;
public static void main(String[] args) {
for (int i = 0; i < 6; ++i) {
new FooThread("Thread" + i).start();
}
}
public static void foo1() {
// do something
while (true) {
// do something
synchronized (Main.class) {
System.out.println(Thread.currentThread().getName());
}
try {
Thread.sleep(SLEEP_TIME);
} catch (InterruptedException e) {}
}
}
public static void foo2() {
while (true) {
System.out.println(Thread.currentThread().getName());
}
}
}
If your while loop isn't so tight, but yields the CPU with say a short Thread.sleep, you'll see more of the different threads sharing foo in closer proximity.
But again, your code also proves that your Thread names *are8 being displayed, but that you're only seeing one name likely because that thread is hogging the CPU.
Another option is to get all the Thread stacks and look for all the threads in the foo() This has the benefit of no overhead or extra code, except to capture the information you want.
BTW: Can you make it clearer why do you need this information as I suspect there is a better way to do what you really want?
If you only want to get the count of threads, use a thread-safe counter to store number of threads. Increase the counter when foo() begins, and decrease the counter when foo() exits.
If you need to get the names, use a hash set (or list if there are duplicates of thread names) to store the names: Add the name when foo() begins, and remove the name when foo() exits. Make sure the access to hash set is thread safe. You also need another method to print out the content of the hash set, so you can call it any time to see what are the name of threads executing foo().
You can put the name into a list when the method starts (in a synchronized block) and remove it at the end again.
List allTheNames = Collections.synchronizedList(new ArrayList<String>());
public void foo() {
allTheNames.add(Thread.currentThread().getName());
// now allTheNames contains all the names of all threads currently in this method.
System.out.println(allTheNames.toString());
allTheNames.remove(Thread.currentThread().getName());
}
Of course, if you change the name of the thread in the meantime that wont work, but why would you do so?
You could also store the Thread itself if you need other informations that the name.

java: Passing a class reference to another thread

I'm trying to learn how to use multithreading in Java. I have a main and two classes which extend Thread, A and B. I want the main to start A, which makes multiple calls to B. Once A is finished, I want B to send something to main.
The main creates two threads, one A and one B, and then starts both threads. A does something, which will then pass on a result to B. The main then collects an answer from B and does something else. I don't know how to get the total from B back to the main.
I'm also not sure how to instantiate the two classes (threads) but then give A a reference of B since Java uses pass-by-value. Can someone give me some pointers.
public static void main(String[] args)
{
B b = new B();
A a = new A(100, b);
B.start();
A.start();
A.join(); // Waiting for A to die
// Here I want to get a total from B, but I'm not sure how to go about doing that
}
public class A extends Thread
{
private int start;
// Some reference to B
B b;
public A (int n, B b) {
int start = n;
this.b = b;
}
public void run() {
for (int i = 0; i < n; i++) {
b.add(i);
}
}
}
public class B extends Thread
{
private int total;
public B () {
total = 0;
}
public void add(int i) {
total += i;
}
}
I changed your example code into what I consider to be a more meaningful example.
Communication between threads is usually handled through shared data (or channels like pipes, sockets - but I wont go there...). And while it is perfectly alright to have this shared data contained within the thread classes I have seperated the shared data from the data/methods used to administer the threads.
I hope this helps you to understand the relationship between threads and data objects.
public class TestThreads {
public static void main(String[] args)
{
DataShare ds = new DataShare();
B b = new B(ds);
A a = new A(100, ds);
b.start();
a.start();
try {
a.join(); // Waiting for A to die
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println ("Accumulated total from B = " + b.getTotal());
b.endThread();
}
}
public class DataShare {
private int value;
public DataShare () {
value = -1;
}
public synchronized boolean setValue(int val) {
boolean valueSet = false;
if (value == -1) {
value = val;
valueSet = true;
}
return valueSet;
}
public synchronized int getValue() {
int val = value;
value = -1;
return val;
}
}
public class A extends Thread {
private int max;
private DataShare dataShare;
public A (int n, DataShare ds) {
max = n;
dataShare = ds;
}
public void run() {
int i = 0;
while (i < max) {
if (dataShare.setValue(i)) {
i++;
}
}
}
}
public class B extends Thread {
private int total;
private DataShare dataShare;
private boolean running = false;
public B (DataShare ds) {
dataShare = ds;
total = 0;
}
public void run() {
running = true;
while (running) {
int nextValue = dataShare.getValue();
if (nextValue != -1) {
total += nextValue;
}
}
}
public int getTotal() {
return total;
}
public synchronized void endThread() {
running = false;
}
}
I am aware that this naive example is far from optimal since both threads are wasting precious cycles while waiting for the value to be set/read. I just wanted to keep the example as simple as possible while still addressing the point I'm trying to make.
A decent way to do it. You just pass an instance of class A:
public class Foo {
public void doFoo() {..} // that's the method you want to use
}
public class Bar {
private Foo foo;
public Bar(Foo foo) {
this.foo = foo;
}
public void doSomething() {
foo.doFoo(); // here you are using it.
}
}
And then you can have:
Foo foo = new Foo();
Bar bar = new Bar(foo);
bar.doSomething();
First of all, B should not be a thread. If all it does is respond to messages from A, then it can just be an object like any other.
Second, while everyone says java uses pass by value, the confusing part is that object references are passed by value, so objects are effectively passed by reference. Thus, you can pass B to A, and get the total from your copy of B.
If we look at your code:
B b = new B();
A a = new A(100, b);
B.start();
A.start();
A.join(); // Waiting for A to die
// Here I want to get a total from B, but I'm not sure how to go about doing that
You are passing a pointer of b to A. That means that if class A only accesses class B directly (it does not replace it with a new instance of B) that the object should contain anything that class A did to it. In other words, both your main code and class A work on the same object of B. So you should be able to get the total of b simply by asking the object you have instantiated in main.
So if you call
b.total();
at the end of main, it should return your value (of course you must ensure that thread A will not make changes to it after retrieving the value).
I assume that you are trying to achieve communication between the two threads you create in the main method. This is, however, not happening. I made a few changes to your code and included it below to show what I think you wanted to do.
First, a few corrections of your examples:
You cannot use class names (A and B) when referencing thread objects as you do in the main method. Use the object names instead (a and b).
In class A constructor you are creating a new local variable start instead of referencing the member variable. Hence: int start = n should be start = n
I'm guessing you want to loop the number of times set in constructor. Hence for (int i = 0; i < n; i++) { should be for (int i = 0; i < start; i++) {
Pass by reference/value is not really relevant here. Object references are passed by value as anything else is. It is, however, the contents of the reference variable (the object address) which is interesting and that will not change. In other words, when passing an object reference to a method, the method WILL address that specific object, and any change made to the contents of the objects will be visible outside the method as well.
Here are your examples with a few corrections as I think you intended them.
public class TestThreads {
public static void main(String[] args)
{
B b = new B();
A a = new A(100, b);
b.start();
a.start();
try {
a.join(); // Waiting for A to die
} catch (InterruptedException e) {
e.printStackTrace();
}
// Getting a total from b is simple, if you provide the method for it
System.out.println ("Accumulated total from B = " + b.getTotal());
}
}
public class A extends Thread {
private int start;
// Some reference to B
B b;
public A (int n, B b) {
start = n;
this.b = b;
}
public void run() {
for (int i = 0; i < start; i++) {
b.add(i);
}
}
}
public class B extends Thread {
private int total;
public B () {
total = 0;
}
public void add(int i) {
total += i;
}
public int getTotal() {
return total;
}
}
Now, here is the problem with these examples:
An object is not a thread and vice versa. In the main thread (lets call that thread tM) You are creating an object of class B and forking a new thread (thread tB) starting in its run() method. However, since you did not override the run method, the threat ends immediately after creation.
Then you create an object of class A. Gives it the reference to object b (which has nothing to do with thread tB) and fork a new thread (thread tA). Here you did implement a run() method. The result is the following:
Thread tM did the initial work and is now waiting for thread tA to finish.
Thread tB was started and died immediately afterwards
Thread tA is doing all the work of incrementing the counter of object a, and making object b add the counter to its sum.
When tA finished after 100 increments tM wakes up and acquires the sum from object b (which again has nothing to do with thread tB).

Why does this thread data race?

I am new to threads and learning. Why does this data race? I know how to do it using the Synchronized(){} method but not with the modifier.
public class SyncMethodDataRace extends Thread {
private static int common = 0;
public synchronized void run(){
int local = common;
local++;
common = local;
}
public static void main(String[] args) throws InterruptedException {
SyncMethodDataRace[] allThreads = new SyncMethodDataRace[20000];
for(int i = 0; i < allThreads.length; i++){
allThreads[i] = new SyncMethodDataRace();
}
for(SyncMethodDataRace d: allThreads){
d.start();
}
for(SyncMethodDataRace d: allThreads){
d.join();
}
System.out.println(common);
}
}
By making run method synchronized you did not achieve the desired synchronization. A synchronized method locks on the current instance of the class. In your example, no other thread is calling the run method of another thread, so there is no blocking.
In your case you probably need a static object that is shared among all instances to synchronize on, ie:
private static Object syncObject = new Object();
public void run() {
synchronized (syncObject) {
//....
}
}

Categories