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.
Related
Below specified code snippet prints numbers in sequence with synchronizing three threads using wait() and notify() methods. But the requirement is to achieve the same using reentrant locking mechanism.
class JoinTask {
private int currentRank = 1;
public void doJob(int rank, int printNo) {
synchronized (this) {
while (rank != currentRank) {
try {
System.out.println("going to wait by thread:" + printNo);
wait();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
System.out.println("Job:" + printNo + " : " + currentRank);
currentRank++;
notifyAll();
}
}
}
public class ThreeThreadsPlay {
public static void main(String[] args) {
final JoinTask task = new JoinTask();
Thread A = new Thread() {
public void run() {
int k = 1;
for (int i = 1; i < 30; i++) {
task.doJob(k, 1);
k = k + 3;
}}};
Thread B = new Thread() {
public void run() {
int k = 2;
for (int i = 1; i < 30; i++) {
task.doJob(k, 2);
k = k + 3;
}}};
Thread C = new Thread() {
public void run() {
int k = 3;
for (int i = 1; i < 30; i++) {
task.doJob(k, 3);
k = k + 3;
}}};
C.start();
B.start();
A.start();
}}
How can I achieve the same using reentrant locking?
Any other example using reentrant locking to provide such mechanism will also help. Furthermore, any information provided in this context will be highly appreciated.
Here's a proper implementation with ReentrantLock/Conditional. Note carefully the differences between this and what you attempted. The lock acquisition and release should really be handled in a try-finally block to avoid a lock being kept indefinitely, but you can find examples of that in other questions.
class JoinTask {
private int currentRank = 1;
final ReentrantLock l = new ReentrantLock();
final Condition c = l.newCondition();
public void doJob(int rank, int threadNumber) {
l.lock();
while(rank != currentRank) {
c.await();
}
System.out.println("Job:" + threadNumber + " : " + currentRank);
currentRank++;
c.signalAll();
l.unlock();
}
}
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.
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'm writing a demo program to explain how to regulate the concurrency of a crowd of threads in Java, but the result is not as I expected. This is the code:
package parcountSyncStat;
public class Parcount extends Thread {
private static int N=1000;
private static Integer x=0;
public static void main(String[] args) throws InterruptedException {
Thread[] t = new Thread[N];
int i;
for (i = N-1; i >= 0; i--) {
t[i]=new Parcount();
t[i].start();
}
for ( i=N-1; i>=0; i-- ) t[i].join();
System.out.println(x);
}
public void run() { synchronized(x) { x++; } }
}
In a nutshell, 1000 threads try to increment the same integer x. To preserve consistency, I encacsulate the increment in a synchronized block. The parent thread waits for all processes to finish, and then prints the final value of x, which should be 1000. But it isn't. My question is: why? I'm I wrong somewhere?
Note that I obtain the expected result by implementing a class that encapsulates the integer with a synchronized "Increment" method. But replacing the synchronized with a lock/unlock pair does not work either. I'm using Eclipse and did try both openjdk and oracle jdk, with similar results.
Thanks
x++ creates a new Integer object - so every time you run that statement the lock used becomes different. If you want one single lock for all you thread, create an ad hoc object:
private static final Object lock = new Object();
and synchronize on that lock.
Thanks to assylias: here is the complete code:
public class Parcount extends Thread {
private static int N=1000;
private static Integer x=0;
private static final Object lock = new Object();
public static void main(String[] args)
throws InterruptedException {
Thread[] t = new Thread[N];
int i;
for ( i=N-1; i>=0; i-- ) {
t[i]=new Parcount();
t[i].start();
}
for ( i=N-1; i>=0; i-- ) t[i].join();
System.out.println(x);
}
public void run() { synchronized(lock) { x++; } }
}
The following code uses the owner of your shared resource x, the class Example, as the instance to synchronize with. You may try changing your code like this:
public class Example extends Thread {
public static void main(String[] args) throws InterruptedException {
Thread[] t = new Thread[N];
for (int i = N - 1; i >= 0; i--) {
t[i] = new Example();
t[i].start();
}
for (int i = N - 1; i >= 0; i--) t[i].join();
System.out.println(x);
}
private static int N = 1000;
private static int x = 0;
#Override public void run() {
synchronized (Example.class) { x++; }
}
}