I cannot reach the last line in my code even though I used synchronized.
However, if I add something between the loop, it worked well.
public static void main(String[] args) {
int test_time = 5;
for (int i = 0; i < 100000; i++) {
//warm up
}
long t = 0;
t = System.currentTimeMillis();
byte[] b = new byte[0];
for (int i = 0; i < test_time; i++) {
new Thread(new Runnable() {
#Override
public void run() {
String i = getUserInf(); //get something from web
synchronized (b) {
++times;
System.out.println(times);
}
}
}).start();
}
while (times != test_time){
// System.out.println(String.format("times=%s,test_time=%s", times,test_time));
// if i added this line, it worked well
}
System.out.println("time:" + (System.currentTimeMillis() - t));
}
You need to declare your variable times as volatile int. Because when it's read in the while loop from the main thread, it is not guarded by b. The call to System.out.println is synchronized, so the value of times gets updated and becomes visible.
Related
public class ThreadsDemo {
public static int n = 0;
private static final int NTHREADS = 300;
public static void main(String[] argv) throws InterruptedException {
final CountDownLatch cdl = new CountDownLatch(NTHREADS);
for (int i = 0; i < NTHREADS; i++) {
new Thread(new Runnable() {
public void run() {
// try {
// Thread.sleep(10);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
n += 1;
cdl.countDown();
}
}).start();
}
cdl.await();
System.out.println("fxxk, n is: " + n);
}
}
Why the output is "n is: 300"? n isn't explicitly synchronized. And if I uncomment "Thread.sleep", the output is "n is: 299 or less".
I changed your code this way:
private static final int NTHREADS = 300;
private static AtomicInteger n = new AtomicInteger();
public static void main(String[] argv) throws InterruptedException {
final CountDownLatch cdl = new CountDownLatch(NTHREADS);
for (int i = 0; i < NTHREADS; i++) {
new Thread(new Runnable() {
public void run() {
n.incrementAndGet();
cdl.countDown();
}
}).start();
}
cdl.await();
System.out.println("fxxk, n is: " + n);
}
You have to deal with racing-conditions. All the 300 threads are modifying n concurrently. For example: if two threads would have read and increment n concurrently than both increment n to the same value.
That was the reason why n wasn't always 300, you lost one increment in such a situation. And this situation could have occurred zero or many times.
I changed n from int to AtomicInteger which is thread safe. Now everything works as expected.
You better use AtomicInteger.
This question will help you with description and example: Practical uses for AtomicInteger
Static context need to have lock on the class and not on the Object. If you need a static variable to be synchronized and do not need it to be cached inside the thread locally you need to declare it as volatile.
public class ThreadsDemo {
public static int n = 0;
private static final int NTHREADS = 30;
public static void main(String[] argv) throws InterruptedException {
final CountDownLatch cdl = new CountDownLatch(NTHREADS);
for (int i = 0; i < NTHREADS; i++) {
new Thread(new Runnable() {
public void run() {
for (int j = 0; j < 1000; j++) // run a long time duration
n += 1;
cdl.countDown();
}
}).start();
}
cdl.await();
System.out.println("fxxk, n is: " + n);
}
}
output "n is: 29953"
I think the reason is, the threads run a short time duration, and the jvm don't make a context switch.
Java static field will be synchronized among threads?
No. You should make it volatile or synchronize all access to it, depending on your usage patterns.
I am wondering why the result is not 400 000. There are two threads why does it gets blocked?
class IntCell {
private int n = 0;
public int getN() {return n;}
public void setN(int n) {this.n = n;}
}
class Count extends Thread {
private static IntCell n = new IntCell();
#Override public void run() {
int temp;
for (int i = 0; i < 200000; i++) {
temp = n.getN();
n.setN(temp + 1);
}
}
public static void main(String[] args) {
Count p = new Count();
Count q = new Count();
p.start();
q.start();
try { p.join(); q.join(); }
catch (InterruptedException e) { }
System.out.println("The value of n is " + n.getN());
}
}
Why there is so problem with that?
Because the way you increment your variable is not an atomic operation indeed to increment it you:
Get the previous value
Add one to this value
Set a new value
They are 3 operations not done atomically you should either us a synchronized block or use an AtomicInteger instead.
With a synchronized block it would be something like:
synchronized (n) {
temp = n.getN();
n.setN(temp + 1);
}
With an AtomicInteger you will need to rewrite your code as next:
class IntCell {
private final AtomicInteger n = new AtomicInteger();
public int getN() {return n.get();}
public void incrementN(int n) {this.n.addAndGet(n);}
}
for (int i = 0; i < 200000; i++) {
n.incrementN(1);
}
The approach with an AtomicInteger is non blocking so it will be faster
When two threads access one object at the same time, they interfere with each other, and the result is not deterministic. For example, imagine that p reads the value of n and gets, say, 0, then q reads the same value and gets 0 too, then p sets value to 1 and q also sets it to 1 (because it still thinks that it has value 0). Now the value of n is increased by 1, even though both counters "incremented" it once. You need to use synchronized block to make sure the counters won't interfere with each other. See https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html for more.
The problem here is that you allow for race conditions. Consider the block inside the loop:
temp = n.getN();
n.setN(temp + 1);
The code context switch between the time you get the current N and by the time you increment it, making you set an "old" value. One way around this is to ensure the inner part of the loop runs in a synchronized block:
for (int i = 0; i < 200000; i++) {
synchronized (n) { / Here!
temp = n.getN();
n.setN(temp + 1);
}
}
class TestSync {
public static void main(String[] args) throws InterruptedException {
Counter counter1 = new Counter();
Counter counter2 = new Counter();
Counter counter3 = new Counter();
Counter counter4 = new Counter();
counter1.start();
counter2.start();
counter3.start();
counter4.start();
counter1.join();
counter2.join();
counter3.join();
counter4.join();
for (int i = 1; i <= 100; i++) {
if (values[i] > 1) {
System.out.println(String.format("%d was visited %d times", i, values[i]));
} else if (values[i] == 0) {
System.out.println(String.format("%d wasn't visited", i));
}
}
}
public static Integer count = 0;
public static int[] values = new int[105];
static {
for (int i = 0; i < 105; i++) {
values[i] = 0;
}
}
public static void incrementCount() {
count++;
}
public static int getCount() {
return count;
}
public static class Counter extends Thread {
#Override
public void run() {
do {
synchronized (count) {
incrementCount();
values[getCount()]++;
}
} while (getCount() < 100);
}
}
}
That is a code from one online course. My task is to make this code visit each element of array only once (only for elements from 1 to 100). So I have added simple synchronized block to run method. In case of using values inside of that statement everything works. But with count it doesn't want to work.
What the difference? Both of this objects are static fields inside of the same class. Also I have tried to make count volatile but it hasn't helped me.
PS: a lot of elements are visited 2 times and some of them even 3 times. In case of using values in synchronized all elements are visited only once!!!
Integer is immutable. The moment you call increment method, You get a new object and reference of count variable gets changed and hence leads to an issue.
I would like to compare thread performance on solaris/linux/windows 64 bit JVM's, with the below code.
I personally, prefer this style of coding for threading, because you have a method performing some computation and you would like to run that computation on separate thread. It does not look intuitive for me launch an object using Thread class. So, Please suggest me for alternate code style, on same lines(if required).
public class Dummy2 {
private static int NUM_OF_THREADS=100000;
public void loopSomeTime() {
Thread t = new Thread(new Runnable(){
public void run(){
int count = 0;
for(int i = 0; i < 1000000; ++i){
count++;
}
System.out.println(count);
}
});
t.start();
}
public static void main(String[] args){
long beginTime = System.nanoTime();
for(int i =0; i < NUM_OF_THREADS ; i++){
Dummy2 d = new Dummy2();
d.loopSomeTime();
}
//I need to wait here
long endTime = System.nanoTime() - beginTime;
System.out.println(endTime/(1000*1000) + "milliseconds");
}
}
How do i wait for all threads to complete before the computation of endTime in MainThread?
Note: I am java beginner and learning Java threads
The key here is you need some way to wait for all of the threads to complete. However, threads are low-level constructs that are a pain to manage correctly.
Using higher-level constructs, you can push some of the tricky dirty work into the Java framework and focus on what you are trying to do: waiting for the threads to complete.
Here is some Java that illustrates the overall design I recommend. It is not complete, but should be a good start.
public static void main(String[] args) {
final int threads = 1000;
ExecutorService exec = Executors.newFixedThreadPool(threads);
List<Future<?>> futures = new LinkedList<>();
final long start = System.currentTimeMillis();
for (int i = 0; i < threads; ++i) {
futures.add(exec.submit(makeTask()));
}
while (!futures.isEmpty()) {
Iterator<Future<?>> it = futures.iterator();
while (it.hasNext()) {
if (it.next().isDone()) {
it.remove();
}
}
}
final long duration = System.currentTimeMillis() - start;
// TODO: report the difference.
}
private static Runnable makeTask() {
// TODO: return a Runnable that does stuff.
return null;
}
You need to keep track of all of the threads and call join on each one.
public class Test {
private static int NUM_OF_THREADS = 100000;
// Keep track of my thread.
private Thread thread;
public void loopSomeTime() {
thread = new Thread(new Runnable() {
public void run() {
int count = 0;
for (int i = 0; i < 1000000; ++i) {
count++;
}
System.out.println(count);
}
});
thread.start();
}
public void waitToFinish() throws InterruptedException {
thread.join();
}
public static void main(String[] args) throws InterruptedException {
List<Test> loopers = new ArrayList<>();
long beginTime = System.nanoTime();
for (int i = 0; i < NUM_OF_THREADS; i++) {
Test d = new Test();
d.loopSomeTime();
// Keep track of all loopers.
loopers.add(d);
}
//I need to wait here
for (Test t : loopers) {
t.waitToFinish();
}
long endTime = System.nanoTime() - beginTime;
System.out.println(endTime / (1000 * 1000) + "milliseconds");
}
}
I had my code working (at least somewhat) and I must have changed something, because now it won't even launch. There's no shown errors within the code, but when I try to run it this is what appears:
Exception in thread "Thread-2" java.lang.NullPointerException
at azsystem3.Add.run(Main.java:57)
at java.lang.Thread.run(Thread.java:662)
and (Main.java:57) is this line: sum.s+=a[i];
How do I fix it?
Here's my relevant code:
package azsystem3;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Fill implements Runnable{
int []a;
static Random b = new Random();
int start;
int end;
public Fill(int[]a,int start,int end){
this.a=a;
this.start=start;
this.end=end;
}
public void run(){
for(int i=this.start;i<this.end;i++){
a[i]=b.nextInt(100);
}
}
}
class value{
int s;
}
class Add implements Runnable{
value sum;
Lock L ;
int[]a;
int start;
int end;
//public long sum=0;
public Add(int[]a,int start, int end,Lock L,value s){
this.L=L;
this.start=start;
this.end=end;
sum=s;
}
public void run(){
int i;
for( i=start;i<end;i++)
L.lock();
sum.s+=a[i];
L.unlock();
}
}
class main {
public static void main(String[] args) {
value sum=new value();
Lock Lock=new ReentrantLock();
int[] array = new int[100000];
Scanner sc=new Scanner (System.in);
System.out.println ("Enter number : ");
int n = sc.nextInt();
int tmp = 100000 / n;
Thread[] t = new Thread[n];
for (int i = 0; i < n; i++) {
t[i] = new Thread(new Fill(array, (i) * tmp, (i + 1) * tmp));
t[i].start();
}
for (int i = 0; i < n; i++) {
try {
t[i].join();
} catch (InterruptedException exception) {
}
}
Thread[] t1 = new Thread[n];
Add[] add = new Add[n];
long start = System.currentTimeMillis();
for (int i = 0; i < n; i++) {
add[i] = new Add(array, (i) * tmp, (i + 1) * tmp,Lock,sum);
t1[i] = new Thread(add[i]);
t1[i].start();
}
for (int i = 0; i < n; i++) {
try {
t1[i].join();
} catch (InterruptedException exception) {
}
}
long end = System.currentTimeMillis();
System.out.println("sum : " + sum);
System.out.println("time : " + (end - start) + "ms");
}
}
Any suggestions?
Thread-safety does not only requires locking on run()-method in your code, but you should also make your private members of class Add, especially the sum member, final. Otherwise a Thread might see a not fully initialized object of type value where the sum-member is still null.
And note: Please try to follow standard Java code conventions for better readability.
Another observation, this code
for( i=start;i<end;i++) // missing opening bracket {
L.lock();
sum.s+=a[i];
L.unlock(); // missing closing bracket }
is equivalent to:
for( i=start;i<end;i++) {
L.lock();
}
sum.s+=a[i];
L.unlock();
I have no trust in any thread-safety here because of improper handling of brackets and therefore locking.
While it looks like a thread-safety issue, the reason for the NullPointerException is quite simple:
In the constructor for the Add class you forgot to assign the int array instance variable a, i.e. a simple this.a=a; is missing.
That’s a reason why you should declare every instance variable as final whenever possible. Then the compiler will tell you about every missing value assignment.
Of course, you will have to fix the missing braces in the Add.run() method as well as otherwise you will get a dead-lock. In your case only the first thread threw a NullPointerException while all other threads were waiting forever.