Reputation: 3
//Initially, I wanted to compare synchronized with Lock
public class SynchronizedVSLock {
static final Lock lock = new ReentrantLock();
static final int loopTime = 10;
static final int numOfThread = 6;
static final Random random = new Random();
static final Semaphore runningThreadsNum = new Semaphore(numOfThread);
public static void main(String[] args) throws InterruptedException {
long startTime = System.currentTimeMillis();
for (int i = 0; i < numOfThread - 1; i++) {
new Thread(new Test1()).start();
}
new Thread(new Test1()).join();
runningThreadsNum.acquire(numOfThread);
long endTime = System.currentTimeMillis();
System.out.println(endTime - startTime);
}
static class Test1 implements Runnable {
@Override
public void run() {
try {
runningThreadsNum.acquire();
} catch (InterruptedException e) {
throw new RuntimeException();
}
for (int i = 0; i < SynchronizedVSLock.loopTime; i++) {
SynchronizedVSLock.lock.lock();
System.out.println(SynchronizedVSLock.random.nextDouble());
SynchronizedVSLock.lock.unlock();
}
runningThreadsNum.release();
}
}
static class Test2 implements Runnable {
@Override
public void run() {
try {
runningThreadsNum.acquire();
} catch (InterruptedException e) {
throw new RuntimeException();
}
for (int i = 0; i < SynchronizedVSLock.loopTime; i++) {
synchronized (SynchronizedVSLock.lock) {
System.out.println(SynchronizedVSLock.random.nextDouble());
}
}
runningThreadsNum.release();
}
}
}
The general idea is to create several threads to concurrently execute the task of outputting random numbers, respectively using the two synchronization mechanisms of lock and synchronized. Finally, the program running time is output as an indicator. Use semaphore to ensure that the Main thread doesn't get the final elapsed time until all the children have finished But I've found that often the Main thread gets all the permissions before the other child threads run, and then prints a very small run time, just a millisecond or two, and I don't know what's wrong.
Upvotes: 0
Views: 69
Reputation: 81074
You're joining a thread that you're not starting, not waiting for any of the threads that you started in your loop:
for (int i = 0; i < numOfThread - 1; i++) {
new Thread(new Test1()).start();
}
new Thread(new Test1()).join();
Calling join()
on an unstarted thread returns immediately. This means that your initial thread can acquire all 6 permits for the semaphore before the first Test1
thread even begins execution, which means it will simply print the time and exit.
You should consider using a CountDownLatch
instead of a sempahore here, as this is the textbook use case for it.
Upvotes: 1
Reputation: 2017
You initialize your semaphore with all the permits required by your main to continue on line runningThreadsNum.acquire(numOfThread).
static final Semaphore runningThreadsNum = new Semaphore(0); // should be zero
Upvotes: 1