Why is count 0?
I start the thread 1 then I start thread 2. Count should be 2000. But it shows count to be 0. Someone please explain in simple terms.
public class App {
private int count = 0;
public static void main(String[] args) {
App app = new App();
app.doWork();
}
public void doWork(){
Thread t1 = new Thread(new Runnable(){
public void run(){
for(int i = 0;i < 10000;i++){
count++;
}
}
});
Thread t2 = new Thread(new Runnable(){
public void run(){
for(int i = 0;i < 10000;i++){
count++;
}
}
});
t1.start();
t2.start();
System.out.println("Count is: " + count);
}
}
At the time you're printing out your thread count, the threads have not finished executing yet.
To demonstrate, add a Thread.sleep() instruction before printing out the thread count:
public class App {
private int count = 0;
public static void main(String[] args) throws InterruptedException {
App app = new App();
app.doWork();
}
public void doWork() throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 10000; i++) {
count++;
}
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 10000; i++) {
count++;
}
}
});
t1.start();
t2.start();
Thread.sleep(5000);
System.out.println("Count is: " + count); // Count is: 20000
}
}
Also note that operations on primitives are not thread-safe and that the count++ operation is not atomic. You should synchronize access to your count variable, or use an AtomicInteger or LongAdder instead of an int. As it stands, you might end up with a count anywhere between zero and 20,000.
Integer's increment is not safe to multithreading. You should use AtmoicInteger like this:
public class App {
private AtomicInteger count = new AtomicInteger(0);
public static void main(String[] args) throws InterruptedException {
App app = new App();
app.doWork();
}
public void doWork() throws InterruptedException {
Thread t1 = new Thread(new Runnable(){
public void run(){
for(int i = 0;i < 10000;i++){
count.getAndIncrement();
}
}
});
Thread t2 = new Thread(new Runnable(){
public void run(){
for(int i = 0;i < 10000;i++){
count.getAndIncrement();
}
}
});
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Count is: " + count);
}
}
It is because you are printing count in main thread.
Main thread executed in its normal way , before child thread started.
That's why your count is 0 ,
try to print count after a while , like put Thread.sleep(2000) before printing it.
You need to make the code block which increments the count as synchronized in order to avoid the race condition.
In addition to this there are multiple ways to solve this problem-
1. Hard code Thread.sleep(miliseconds value) in Main thread. [Not recommended]
2. join() the two threads to the main Thread so that the control returns to the main thread only when the execution of the two threads is complete.
public class App implements Runnable {
private int count = 0;
public static void main(String[] args) throws InterruptedException {
App app = new App();
app.doWork();
}
public void doWork() throws InterruptedException {
Thread t1 = new Thread(this, "Thread - 1");
Thread t2 = new Thread(this, "Thread - 2");
t1.start();
t2.start();
//1.
t1.join();
t2.join();
//2.
//Thread.sleep(1000);
System.out.println("Count is: " + count); // Count is: 2000
}
#Override
public synchronized void run() {
for (int i = 0; i < 1000; i++) {
count++;
}
}
}
Related
I am running two variations of similar code, expecting same result to appear however the output shows unexpected results.
variation1 with Synchronized block
public class SomeTask implements Runnable {
public int count = 0;
#Override
public void run() {
synchronized (this) {
for (int i = 0; i < 1_000_000; i++) {
count++;
}
}
}
}
public class TestMemory {
public static void main(String[] args) {
SomeTask task1 = new SomeTask();
Thread t1 = new Thread(task1);
Thread t2 = new Thread(task1);
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Main Thread Executed");
System.out.println(Thread.currentThread().getName() + ": " + task1.count);
}
}
output
Main Thread Executed
main: 2000000
no matter how many times we run
variation2 with ReentrantLock
public class SomeTask implements Runnable {
public int count = 0;
#Override
public void run() {
Lock lock = new ReentrantLock();
try {
lock.lock();
for (int i = 0; i < 1_000_000; i++) {
count++;
}
} finally {
lock.unlock();
}
}
}
public class TestMemory {
public static void main(String[] args) {
SomeTask task1 = new SomeTask();
SomeTask task2 = new SomeTask();
Thread t1 = new Thread(task1);
Thread t2 = new Thread(task1);
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Main Thread Executed");
System.out.println(Thread.currentThread().getName() + ": " + task1.count);
}
}
output
Main Thread Executed
main: 1023239
changes the value in multiple executions
Conclusion
Expected result is 2000000 in both the cases, however only synchronized block is working as expected.
Ah my bad I was using two different object of ReentrantLock
Modified Code
public class TestMemory {
public static void main(String[] args) {
Lock lock = new ReentrantLock();
SomeTask task1 = new SomeTask(lock);
SomeTask task2 = new SomeTask(lock);
Thread t1 = new Thread(task1);
Thread t2 = new Thread(task1);
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Main Thread Executed");
System.out.println(Thread.currentThread().getName() + ": " + task1.count);
}
}
----------
public class SomeTask implements Runnable {
public int count = 0;
Lock lock;
public SomeTask(Lock lock) {
this.lock = lock;
// TODO Auto-generated constructor stub
}
#Override
public void run() {
try {
lock.lock();
for (int i = 0; i < 1_000_000; i++) {
count++;
}
} finally {
lock.unlock();
}
}
}
Output
Main Thread Executed
main: 2000000
I want to learn how to use the synchronized method in java and implemented the following code.
public class checkThread {
volatile int i = 0;
public void increment() {
i++;
}
}
public class TestSync extends checkThread{
public static void main(String[] args) {
checkThread ct1 = new checkThread();
Object iLock = new Object();
for(int i = 0 ; i < 10 ; i++) {
extracted(ct1, iLock);
}
}
private static void extracted(checkThread ct1, Object iLock) {
synchronized (iLock) {
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
for(int a = 0; a < 1000; a++) {
ct1.increment();
}
}
});
t1.start();
}
synchronized (iLock) {
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
for(int a = 0; a < 1000; a++) {
ct1.increment();
}
}
});
t2.start();
}
synchronized (iLock) {
System.out.println(ct1.i);
}
}
}
However the output I get is not at all synchronized!
1000
2000
4000
6000
8000
9000
11575
13575
15575
17459
Why am I getting such an output and not the desired value of i in the multiples of 1000?
If you are trying to make sure that the run() method will be completed by one thread before the other one start; then you need to synchronize the content inside the run method, not the thread creation part.
In your specific example, you need to have an object that can be accessed by both the threads, and then acquire the lock of that object.
Let me add an example below by changing your code; but this may not be the best way; just trying to explain the point.
checkThread iLock = new checkThread();
public void someMethod() {
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
synchronized (iLock) {
for(int a = 0; a < 1000; a++) {
ct1.increment();
}
}
});
t1.start();
}
Thread t2 = new Thread(new Runnable() {
#Override
public void run() {
synchronized (iLock) {
for(int a = 0; a < 1000; a++) {
ct1.increment();
}
}
});
t2.start();
}
synchronized (iLock) {
System.out.println(ct1.i);
}
}
This question already has answers here:
Threading and synchronized methods
(3 answers)
Closed 4 years ago.
I'm very novice in multithreading in java, so would be very appreciate if someone give me brief explanation of the following:
here is my code:
public class Lesson6 {
private static volatile Long value = 0L;
public static void main(String[] args) throws InterruptedException {
Thread inc = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 100_000; i++) {
synchronized (this){
++value;
}
}
}
});
inc.start();
Thread dec = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 100_000; i++) {
synchronized (this){
--value;
}
}
}
});
dec.start();
inc.join();
dec.join();
System.out.println(value);
}
}
It seems for me, that the output should be zero, but it's never zero. Debugger shows that THIS is always different from time to time as run() methods go. Why does this happen?
Thanx.
Debugger shows that THIS is always different from time to time as run() methods go
Each new Runnable is a different object so this is different in each case.
If you use a common object, the program should work.
BTW I suggest using a primitive long for the value instead of a reference to a Long
public class Lesson6 {
private static volatile long value = 0L;
public static void main(String[] args) throws InterruptedException {
final Object locked = new Object();
Thread inc = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 100_000; i++) {
synchronized (locked){
++value;
}
}
}
});
inc.start();
Thread dec = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 100_000; i++) {
synchronized (locked){
--value;
}
}
}
});
dec.start();
inc.join();
dec.join();
System.out.println(value);
}
}
prints
0
I am getting empty hashmap when I print it, what's the best approach to Share Static volatile variable between threads?
class RunnableDemo implements Runnable {
int i;
RunnableDemo(int i) {
i = i;
}
public void run(){
finResult.put("value"+str(i), 1);
}
public void start () {
System.out.println("Starting " );
if (t == null) {
t = new Thread (this);
t.start ();
}
}
public class TestThread {
public static volatile ConcurrentHashMap<String, Integer> finResult = new ConcurrentHashMap<String, Integer>();
public static void main(String args[]) {
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newCachedThreadPool();
for(int i=0; i < 4; i++){
RunnableDemo task = new RunnableDemo(i);
executor.execute(task);
}
executor.shutdown();
}
System.out.println(TestThread.finResult);
}
System.out.println(TestThread.finResult); This should print the finResult with all the values from threads.
ERROR: local variable t is accessed from within inner class need to be declared final And local variable t1 is accessed from within the class.same with t1.start(); why do I need to declare them final?
public class sync {
public int count = 0;
public static void main(String args[]) {
sync obj = new sync();
obj.dowork();
sync obj1 = new sync();
obj1.dowork1();
System.out.println(count);
}
public void dowork() {
Thread t = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 1000; i++) {
count++;
}
t.start();
}
});
}
public void dowork1() {
Thread t1 = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 1000; i++) {
count++;
}
t1.start();
}
});
}
}
I did what you told me really helpful now it's just Showing: System.out.println("count"+count);
Identifier expected plus reach end of file while parsing
t and t1 objects are limited to scope of methods, make them member variables. Secondly, method calls and statements are called from inside a method..here t.start() & t1.start() are just floating loose inside class ... Same goes for print statement it
should also be called from inside a method.
Call to start method should be after the threads (t,t1) has been initialized. Currently they are used inside the initialization process.
It should be like this :
public void dowork(){
Thread t=new Thread (new Runnable (){
public void run(){
for (int i=0;i<1000;i++){
count++;}
}});
t.start();
}
Also count should be a static variable, as you cannot refer non-static variable from inside a static main method.
Your code be like, following think are corrected:
You make count variable static since it is been access with in static main method.
You trying to call Thread.start with in the run method which is wrong, since Thread.start method will call run method.
public class sync {
public static int count = 0;
public static void main(String args[]) {
sync obj = new sync();
obj.dowork();
sync obj1 = new sync();
obj1.dowork1();
System.out.println(count);
}
public void dowork() {
Thread t = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 1000; i++) {
count++;
}
}
});
t.start();
}
public void dowork1() {
Thread t1 = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 1000; i++) {
count++;
}
}
});
t1.start();
}
}
public class sync {
static int count = 0;
public static void main(String args[]) {
sync obj = new sync();
obj.dowork();
sync obj1 = new sync();
obj1.dowork1();
System.out.println(count);
}
public void dowork() {
Thread t = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 1000; i++) {
count++;
}
}
});
t.start();
}
public void dowork1() {
Thread t1 = new Thread(new Runnable() {
public void run() {
for (int i = 0; i < 1000; i++) {
count++;
}
}
});
t1.start();
}
}