I do not understand why each time I run this code I get different answer ?
Correct answer should be one 98098 two 98099. Anyone have any ideas why this is not working that way ? For example one time answer comes back "one 49047 two 49047" then another time it comes back "one 40072 two 40072". I am so confused at this point and lack any reasonable explanation
public class TestThreads {
public static void main(String[] args){
ThreadOne t1 = new ThreadOne();
ThreadTwo t2 = new ThreadTwo();
Thread one = new Thread(t1);
Thread two = new Thread(t2);
one.start();
two.start();
}
}
class ThreadOne implements Runnable {
Accum a = Accum.getAccum();
public void run(){
for(int x = 0; x < 98; x++){
a.updateCounter(1000);
try{
Thread.sleep(50);
}catch(InterruptedException ex){
}
}
System.out.println("one " + a.getCount());
}
}
class ThreadTwo implements Runnable {
Accum a = Accum.getAccum();
public void run(){
for(int x = 0; x < 99; x++){
a.updateCounter(1);
try{
Thread.sleep(50);
}catch(InterruptedException ex){
}
}
System.out.println("two " + a.getCount());
}
}
class Accum {
private static Accum a = new Accum();
public static Accum getAccum(){
return a;
}
private int counter = 0;
public int getCount(){
return counter;
}
public void updateCounter(int add){
counter += add;
}
private Accum(){ }
}
As you have two threads updating the same data without thread safety, one thread easily overwrites the value set by the other one.
Each thread works on it's own thread cached value. e.g.
Thread 1 adds 1 one hundred times. It has the value 100
Thread 2 adds 1000 one hundred times. It has the value 100000
At this point, the one value is chosen. say it's thread 1's value.
Thread 1 adds 1 one hundred times. It has the value 200
Thread 2 adds 1000 one hundred times. It has the value 100100
This time, thread 2's value is chosen.
In the end only half the updates on average are retained as the value chosen is somewhat random.
You can get to 98099 by declaring the methods in Accum as synchronized.
This will ensure that only one of the threads can access it's information at a time.
As the other answers have pointed out, you are getting unexpected results because there is nothing to stop each thread overwriting what the other had done.
Try this:
class Accum {
private static Accum a = new Accum();
public static synchronized Accum getAccum(){
return a;
}
private int counter = 0;
public synchronized int getCount(){
return counter;
}
public synchronized void updateCounter(int add){
counter += add;
}
private Accum(){ }
}
your problem is this:
private static Accum a = new Accum();
public static Accum getAccum(){
return a;
}
Since its a STATIC there is only one instance shared by all threads. so when you set it in one thread, all threads get the same new value. if you remove the static notifier and instantiate a new object of class Accum for each thread it should work.
Related
There are two threads, A and B, each needing to print the numbers 1 to 100, with the constraint that thread B cannot go ahead of thread A at any point. The threads should operate independently apart from this constraint.
I tried the below approach to do so.
public class Main {
private static volatile int counter=1;
public static void main(String[] args) {
Thread t1= new Thread(()->{
for(;counter<=100;++counter)
{
System.out.println("[T1] local counter is "+counter);
}
});
Thread t2= new Thread(()->{
for(int i=1;i<=100;i++)
{
while(i>=counter)
{
System.out.println("[T2] waiting as counter value reached above A or same "+i);
}
System.out.println("[T2] local counter is "+i);
}
});
t1.start();
t2.start();
}
}
where counter is static variable.
private static volatile int counter = 1;
Is there other alternative to achieve the desired output?
I am having trouble figuring out what my code is doing as this is my first time coding using multiple threads. To start off, in attempt to learn this type of programming I decided to write a miniature program that uses 8 threads to sum a number. However, no matter what I do it seems as if my program never stops when count = 10, it continues onward. I am using 8 threads as I planned on expanding my program to do large calculations. However, these threads are not correlating at all. They are going way past 10. I have used a synchronized method. I have tried a lock. I have tried implementing both at the same time. No matter what, it appears as if the threads still calculate past 10. See below for my current code.
public class calculator implements Runnable {
static int counter = 0;
static int sum = 0;
private synchronized static int getAndIncrement()
{
// System.out.println("counter is : " + counter);
int temp = counter;
counter = counter + 1;
System.out.println("counter is now : " + counter);
return temp;
}
private synchronized void addToSum(int value)
{
// System.out.println("sum : " + sum + " value: " + value);
sum += value;
}
#Override
public void run()
{
// TODO Auto-generated method stub
while(counter < 10)
{
int tempVal = getAndIncrement();
System.out.println("temp val : " + tempVal);
addToSum(tempVal);
// System.out.println("sum is now : " + sum);
}
}
}
This is my main method:
public static void main(String[] args)
{
calculator[] calc = new calculator[8];
Thread[] thread = new Thread[8];
final long startTime = System.currentTimeMillis();
for(int i = 0; i < 8; i++)
{
calc[i] = new calculator();
thread[i] = new Thread(calc[i]);
thread[i].start();
}
while(thread[0].isAlive() ||thread[1].isAlive() || thread[2].isAlive() || thread[3].isAlive() || thread[4].isAlive() || thread[5].isAlive() || thread[6].isAlive() || thread[7].isAlive())
{}
final long endTime = System.currentTimeMillis();
System.out.println(calculator.sum);
System.out.println("Execution time : " + (startTime - endTime));
}
I appreciate the help!
The synchronized keyword takes the object
lock. This means that two methods that are synchronized cannot execute on the same object. They will, however, execute concurrently on invocation on 2 different objects.
In your example, your code had 8 objects of calculator. The synchronized methods do not help you. Each thread uses it's separate object. You can completely remove the synchronized keyword, and your code will be semantically equivalent.
To avoid this, use the atomic version of the objects (AtomicInt) or lock on the objects themselves: synchronized(counter){...} but for this to work you will have to change the type to Integer.
I've just tested your sample and found the addToSum method doesn't work as expected here with heavy multi-thread, even if synchronized keyword is present.
Here, as sum variable is static, the method can be made static too.
After adding the static keyword, the behavior is as expected:
private static synchronized void addToSum(int value)
{
sum += value;
}
Here a simple test (addToSum replaced by incSum for simplicity) :
class IncrementorThread implements Runnable {
private static int sum = 0;
private static synchronized void incSum()
{
sum ++;
}
public void run() {
incSum();
Thread.yield();
}
}
void testIncrementorThread1() {
ExecutorService executorService = Executors.newCachedThreadPool();
//ExecutorService executorService = Executors.newSingleThreadExecutor() // result always ok without needing concurrency precaution
for(int i = 0; i < 5000; i++)
executorService.execute(new IncrementorThread());
executorService.shutdown();
executorService.awaitTermination(4000, TimeUnit.MILLISECONDS);
System.out.println("res = "+IncrementorThread.sum); // must be 5000
}
Result must be 5000, which is not the case if we remove the static keyword from the method incSum()
This question already has answers here:
Synchronization on immutable objects (in java)
(4 answers)
Closed 6 years ago.
I'm new to java and was trying out synchronization with a sample program to add numbers upto 100 using multiThreading. And following is code i was able to come up with. When i test the code it sometimes gives the correct value of 4590 but sometimes doesnt give the correct value. Can anyone point out what i'm doing wrong
class Counter{
Integer counter = 0;
public void increment(int i){
synchronized (counter){
counter += i;
}
}
}
class ObjectTest implements Runnable{
int i;
Counter blah;
public ObjectTest(Counter counter,int i){
blah =counter;
this.i = i;
}
#Override
public void run() {
blah.increment(i);
}
}
public class SyncTest {
public static void main(String args[]) throws InterruptedException {
ThreadPoolExecutor executor = new ThreadPoolExecutor(4,10,60, TimeUnit.SECONDS,new SynchronousQueue<Runnable>(), new ThreadPoolExecutor.CallerRunsPolicy());
Counter counter = new Counter();
for (int index = 0; index < 100; index++) {
ObjectTest objectTest = new ObjectTest(counter,index);
executor.execute(objectTest);
}
executor.shutdown();
while (!executor.isTerminated()){
Thread.sleep(1000L);
}
System.out.println(counter.counter);
}
}
You can't synchronize on counter because it's an Integer, which is immutable. Therefore counter += i creates a new Integer object, which is not the same that was synchronized on.
You can make it int counter and have a separate Object lock = new Object();, synchronizing on lock.
these are just sample codes to ask my question the other statements are omitted
here the instance of NewClass is being passes both to Foot and Hand objects
and hence all the instances NewClass,foot and hand share the variable sno of NewClass.
public class NewClass {
volatile int sno = 100;
public static void main(String args[])
{
NewClass n = new NewClass();
Foot f = new Foot(n);
Hand h = new Hand(n);
f.start();
h.start();
}
}
public class Foot implements Runnable{
Thread t;
NewClass n;
public Foot(NewClass n)
{
this.n = n;
}
public void run(){
for(int i=0;i<100;i++)
{
System.out.println("foot thread "+ i+" "+n.sno);
n.sno=(-1)*n.sno;
Thread.sleep(1); // surrounded by try-catch
}
}
}
public class Hand implements Runnable {
Thread t;
NewClass n;
public Hand(NewClass n)
{
this.n = n;
}
public void run(){
for(int i=0;i<100;i++)
{
System.out.println("hand thread "+ i+" "+n.sno);
n.sno=(-1)*n.sno;
Thread.sleep(1); // surrounded by try -catch
}
}
}
here the sign of seq.no is changing everytime but when used by the other thread the change is many times not reflected as if the updation is taking time.so please help ,
It is not taking to long to update.
System.out.println("foot thread " + i + " " + n.sno);
n.sno=(-1)*n.sno;
When you have this happening in two threads running in parallel they may be watching the value as positive at the same time. So they both change the value to negative. If you want to control the change you need a semaphore.
In NewClass:
volatile int sno = 100;
final Object semaphore = new Object();
And in your two Runnables:
synchronized (n.semaphore) {
System.out.println("foot thread " + i + " " + n.sno);
n.sno = (-1) * n.sno;
}
I want to understand performance in multithreaded environments. For that I have written a small test that I ran on my machine (quad-core Intel, Windows XP, Sun JDK 1.6.0_20), with surprising results.
The test is basically a thread-safe counter that is synchronized using either the synchronized keyword or an explicit lock. Here is the code:
import java.util.concurrent.locks.ReentrantLock;
public class SynchronizedPerformance {
static class Counter {
private static final int MAX = 1 << 24;
int count;
long lastLog = 0;
private final ReentrantLock lock = new ReentrantLock();
private int incrementAndGet() {
count++;
if (count == MAX) {
long now = System.nanoTime();
if (lastLog != 0) {
long elapsedTime = now - lastLog;
System.out.printf("counting took %.2f ns\n", Double.valueOf((double)elapsedTime / MAX));
}
lastLog = now;
count = 0;
}
return count;
}
synchronized int synchronizedIncrementAndGet() {
return incrementAndGet();
}
int lockedIncrementAndGet() {
lock.lock();
try {
return incrementAndGet();
} finally {
lock.unlock();
}
}
}
static class SynchronizedCounterAccessor implements Runnable {
private final Counter counter;
public SynchronizedCounterAccessor(Counter counter) {
this.counter = counter;
}
#Override
public void run() {
while (true)
counter.synchronizedIncrementAndGet();
}
}
static class LockedCounterAccessor implements Runnable {
private final Counter counter;
public LockedCounterAccessor(Counter counter) {
this.counter = counter;
}
#Override
public void run() {
while (true)
counter.lockedIncrementAndGet();
}
}
public static void main(String[] args) {
Counter counter = new Counter();
final int n = Integer.parseInt(args[0]);
final String mode = args[1];
if (mode.equals("locked")) {
for (int i = 0; i < n; i++)
new Thread(new LockedCounterAccessor(counter), "ca" + i).start();
} else if (mode.equals("synchronized")) {
for (int i = 0; i < n; i++)
new Thread(new SynchronizedCounterAccessor(counter), "ca" + i).start();
} else {
throw new IllegalArgumentException("locked|synchronized");
}
}
}
I made the following observations:
java SynchronizedPerformance 1 synchronized works pretty well, and takes about 15 ns per step.
java SynchronizedPerformance 2 synchronized interferes a lot and takes about 150 ns per step.
When I start two independent processes of java SynchronizedPerformance 2 synchronized each of them takes about 100 ns per step. That is, starting the process a second time makes the first one (and the second) faster.
I don't understand the third observation. What plausible explanations exist for this phenomenon?
You are running into a situation where performance is entirely dependent on how the scheduler operates. In #3, when any other process in the system wants some time (even a little bit), it will suspend one of your 4 threads. If that thread happens to not hold the lock at when it is suspended, its "pair" can now run uncontested, and will make lots of progress (runs at 20x speed compared to the contested situation).
Of course, if it is swapped out when it does hold the lock, its "pair" will make no progress. So you have two competing factors, and the overall runtime depends on the fraction of time the lock is held by a thread and the penalty/bonus you get for each situation. Your bonus is substantial so I would expect some overall speedup like you saw.
The most likely is that there are certain fixed overheads that exist regardless of how many threads exist- for example, garbage collection or other resource management.