Win a copy of Java Concurrency Live Lessons this week in the Threads forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

All Threads should refer same variable with private copy.  RSS feed

 
Ramakrishna Udupa
Ranch Hand
Posts: 254
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi All,

In Multi-Threaded program, we use volatile to a variable. Because if it modified by any threads should reflect in all threads. But, Now my case is reverse. User have a option to create his own number of threads by specifying the number. After that, I've to create that much thread in my program. If he creates 100 threads I can't create 100 variables dynamically. So I want to use one variable, that should refer by all threads with its own copy. I din't specify volatile to that variable. When I run the program, the variable is referred by all threads. But, it's value also reflecting in all threads.

example:


Thread->T1 modify that count as count++; Now the count value becomes 1. When another thread->T2 comes and verify the count value it should be 0(Or I'm expecting), but it refers the count value as 1. How to solve this.

Thanks:
Ramakrishna K.C
 
Rajkamal Pillai
Ranch Hand
Posts: 445
1
Java Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Looks like a Thread synchronization issue?

What happens when you synchronize access to this variable?
 
Jesper de Jong
Java Cowboy
Sheriff
Posts: 15865
81
Android IntelliJ IDE Java Scala Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Maybe what you want is ThreadLocal: it creates a separate instance of a variable for each thread.

Example:
 
Ulf Dittmer
Rancher
Posts: 42970
73
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Using a ThreadLocal would not achieve the aim that a change in one variable is reflected in all threads - so there really should just be a single variable. Synchronizing access to a global object would be the general approach, but if it's as simple as incrementing an integer value, you can use an AtomicInteger for that and don't need the explicit synchronization.
 
Ramakrishna Udupa
Ranch Hand
Posts: 254
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
@Rajkamal Pillai

Changes of that count is reflecting in all threads. Synchronize means threads locks the method or resource. I don't want to lock anything. Just separate value. I mean, when T1 changes count from 0 to 1, then next thread say T2 should read the count as 0 and increment to 1. After that when T1 comes again it should read the value, which T1 changed last time not T2. So T1 should read 1 as count and increment to 2. After T2 come it should read count as 1 which it modified last time and increment to 2. I think I'm clear..

@Ulf Dittmer

but if it's as simple as incrementing an integer value


Yes. I want to just increment the value for separate threads. T1 increases its copy of count and reads from its own copy. It has no business with count which is increments/decrements by T2 or other threads. Same for all threads like T1, T2 etc.,

Thanks:
Ramakrishna K.C
 
Chan Ag
Rancher
Posts: 1090
14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
It's a variable that should be accessible to all the threads. So we have two options.

1. A ThreadLocal variable.
2. A static variable associated with the Runnable.

Now the changes done to this variable by one thread should NOT be seen by other threads. That rules out option 2 and leaves us with just one option-- option 1 . Jesper has already showed how a ThreadLocal variable should be created and used. For more information on ThreadLocal variables, you may like to refer to this page.

I think that should work.

Chan.

[ By the way, I am not sure if we have just two options there for the first case. But those are the only options that I know of/could think of. ]
 
Ulf Dittmer
Rancher
Posts: 42970
73
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm sorry, upon re-reading the first post more carefully I realize that it asks for the opposite of what I thought it did. Ignore my post - ThreadLocal is the way to go.
 
Ramakrishna Udupa
Ranch Hand
Posts: 254
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks All,

I've to call getCount() method right (referring "Jesper de Jong" code)? So, my code structure will be like this,


right?


Thanks:
Ramakrishna K.C
 
Ramakrishna Udupa
Ranch Hand
Posts: 254
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Here I increment. How to set the value to 0. I mean, after count reaches 50, I've to make count 0. How to make that? Can I add one more method like



Thanks:
Ramakrishna K.C
 
Stuart A. Burkett
Ranch Hand
Posts: 679
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ramakrishna Udupa wrote:Here I increment. How to set the value to 0. I mean, after count reaches 50, I've to make count 0. How to make that? Can I add one more method like



Thanks:
Ramakrishna K.C

I would have thought you could do that in your increment method. You just need to check the current value that count.get returns and then use count.set to set the appropriate value.
 
Ramakrishna Udupa
Ranch Hand
Posts: 254
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Oh.. then just by simply calling incrementCount() in method2() and doing this,

will solve my problem. I think I guess right @Stuart A. Burkett

Thanks:
Ramakrishna K.C
 
Chan Ag
Rancher
Posts: 1090
14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ramakrishna Udupa wrote:Oh.. then just by simply calling incrementCount() in method2() and doing this,

will solve my problem. I think I guess right @Stuart A. Burkett

Thanks:
Ramakrishna K.C


I suggest you read Stuart's response again. He is suggesting you can do that in the incrementCount method. So what you can do is retrieve ( get ) the current count. Check ( use an if condition ) if it is 50. If so, set it to 0, otherwise set it to the next value. Does that work 'as intended'?

 
Ramakrishna Udupa
Ranch Hand
Posts: 254
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Sorry for asking this again. Now my code is,



I'm not getting what you are telling guys. Sorry for that.


Thanks:
Ramakrishna K.C
 
Chan Ag
Rancher
Posts: 1090
14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You can do this.



Or you could do this.



Does that help?
Chan.
 
Ramakrishna Udupa
Ranch Hand
Posts: 254
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
@Chan Ag

Yes. That help a lot to learn the concept and coding of ThreadLocal.


Thanks All.
Ramakrishna K.C
 
Ramakrishna Udupa
Ranch Hand
Posts: 254
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi All,

A small modification in my requirement. Suppose I've 2 manager Threads and for each manager 5 worker threads are there. So Structure is like,

Tmanager have Tmanager1, Tmanager2, Tmanager3, Tmanager4, Tmanager5.

Tmanag have Tmanag1, Tmanag2, Tmanag3, Tmanag4, Tmanag5.


So, workers will report after work finished. So all Tmanager child's should share one variable say managerCount. Also all Tmanag child's should share one variable say managCount. Is there any way to do like this? OR Is there any other best way/practices for this.

Thanks:
Ramakrishna K.C
 
Steve Luke
Bartender
Posts: 4181
22
IntelliJ IDE Java Python
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes, the managers would need to create an instance of, say, an AtomicInteger and pass that instance to each of the Threads it manages.


So if you had two Managers you would have two counters. By passing the counter to each of the managed threads you are making sure all of the threads belonging to a single Manager have the same instance. By using final, you are making sure the instance of the AtomicInteger assigned to the variable is visible to all threads and can't be changed, and by using AtomicInteger you are making sure the changes you make to the counter are thread safe.
 
Winston Gutkowski
Bartender
Posts: 10573
65
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ramakrishna Udupa wrote:Yes. That help a lot to learn the concept and coding of ThreadLocal.

However, from what I see, you don't actually need it at all.

As Steve says, AtomicInteger would appear to be all you need, and furthermore the class is not final, so you can extend it to add whatever cycling behaviour you want.

Winston
 
Ramakrishna Udupa
Ranch Hand
Posts: 254
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks All.

Ramakrishna K.C

 
Ramakrishna Udupa
Ranch Hand
Posts: 254
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi All

Using AtomicInteger, I did one sample program. Here is ma code. It is not working properly,

manager.class



worker.class


I'm expecting output,
9 from T1child
8 from T1child
7 from T1child
6 from T1child
5 from T1child
4 from T1child
3 from T1child
2 from T1child
1 from T1child
0 from T1child

9 from T2child
8 from T2child
7 from T2child
6 from T2child
5 from T2child
4 from T2child
3 from T2child
2 from T2child
1 from T2child
0 from T2child

may be or may not be in order.

My current output is:

9 from T1child
8 from T2child
7 from T1child
5 from T1child
4 from T1child
6 from T2child
3 from T1child
1 from T1child
0 from T1child
2 from T2child


Can anybody tell, why this is happening.

Thanks All:
Ramakrishna K.C
 
Steve Luke
Bartender
Posts: 4181
22
IntelliJ IDE Java Python
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You only have one counter that you use - the one in the Manager instance that the main method creates. Here is what you do:

1) in the main thread, in the main method, create a new instance of Manager which creates an AtomicInteger called counter (we will call this main.counter).
2) in the main thread, in the Manager#dowrk() method, loop two times
2.1) For each loop create a new thread named "Tn" and start it
2.1.1) In each "Tn" thread, create a new Worker, passing it main.counter and the thread name.
2.1.2) In the Worker constructor, create a new Manager instance which is never used
2.1.3) In the Worker constructor, create a new Thread with the name "Tnchild" and start it
2.1.3.1) In the new thread, loop decrementing main.counter until it reaches zero and display


So first thing to note is that you are creating more threads than needed: why do you create threads that do nothing but start another thread? Why not just create the Worker from within the main thread?

Second, since you pass the same AtomicInteger between all the workers, all the workers will use the same AtomicInteger. This is per your requirement that "all Tmanager child's [sic] share one variable." You have one Manager, therefore you have one variable. If you want multiple Managers so you get multiple variables, create multiple Managers rather than using just one. If you want one Manager that can start multiple different groups of Workers, with each group sharing the same counter, then don't use an instance variable. Instead create a method local variable in Manager#run() and pass that to each Worker created in that method.
 
Steve Luke
Bartender
Posts: 4181
22
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Also, I wanted to mention if you want the output exactly like what your expectations are (decrements printed in order, with one child going then the next) you will need synchronization. Both threads are decrementing in parallel, so their output will be intertwined. If you want them to be ordered like that you might be better off not using threads, since you look to be intending them to run in series rather than in parallel anyways.
 
Ramakrishna Udupa
Ranch Hand
Posts: 254
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for reply,

First, This is my sample code. In my real code I want These many threads.

Second, I want multiple managers creates an AtomicInteger, only for their child's, not for other managers child's.


As I understood,

1) in the main thread, in the main method, create a new instance of Manager which creates an AtomicInteger called counter (we will call this main.counter).



Manager.class


worker.class


I think I did what you told. Is this Correct way? If this code is right, then I'm not getting the output, what I expected.

Thanks
Ramakrishna K.C
 
Steve Luke
Bartender
Posts: 4181
22
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ramakrishna Udupa wrote:Thanks for reply,

First, This is my sample code. In my real code I want These many threads.

Second, I want multiple managers creates an AtomicInteger, only for their child's, not for other managers child's.


As I understood,

Steven Luke wrote: 1) in the main thread, in the main method, create a new instance of Manager which creates an AtomicInteger called counter (we will call this main.counter).


...

I think I did what you told. Is this Correct way? If this code is right, then I'm not getting the output, what I expected.


Sorry I wasn't clear. The steps I mentioned are what you actually do, which is wrong. The fix was this:
Steven Luke wrote:You have one Manager, therefore you have one variable. If you want multiple Managers so you get multiple variables, create multiple Managers rather than using just one.

Your main method right now (in the broken version) creates one manager, and that one manager creates one counter and multiple Workers. If you want multiple Managers then you need to instantiate multiple Managers in the main method, not just run the run() method on the same Manager multiple times.
 
Ramakrishna Udupa
Ranch Hand
Posts: 254
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
@Steve Luke OMG!! I did such a mistake and I din't recognize myself. So sad. Any way thanks for pointing my mistake.

Thanks:
Ramakrishna K.C
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!