Reputation: 3197
I wrote a simple code to mock concurrency using Lock
and synchronized
.
Source code is as follows:
Task class includes a method named doSomething()
to print the thread name and executing elapsed time.
import java.util.Calendar;
public class Task {
public void doSomething() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
StringBuilder sb = new StringBuilder();
//Thread Name
sb.append("Thread Name: ").append(Thread.currentThread().getName());
//Timestamp for the executing
sb.append(", elaspsed time: ").append(Calendar.getInstance().get(13)).append(" s ");
System.out.println(sb.toString());
}
}
TaskWithLock class
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TaskWithLock extends Task implements Runnable {
private final Lock lock = new ReentrantLock();
@Override
public void run() {
try {
lock.lock();
doSomething();
} finally {
lock.unlock();
}
}
}
TaskWithSync class
public class TaskWithSync extends Task implements Runnable {
@Override
public void run() {
synchronized ("A") {
doSomething();
}
}
}
Main class
public class Main {
public static void runableTasks(Class<? extends Runnable> clz)
throws Exception {
ExecutorService service = Executors.newCachedThreadPool();
System.out.printf("<-- Start executing %s Task --> \n",
clz.getSimpleName());
// Start 3 threads
for (int i = 0; i < 3; i++) {
service.submit(clz.newInstance());
}
// Wait for some time, and then close the executor
TimeUnit.SECONDS.sleep(10);
System.out
.printf("<-- %s Tasks is complet --> \n", clz.getSimpleName());
service.shutdown();
}
public static void main(String[] args) throws Exception {
//Execute tasks with Lock
runableTasks(TaskWithLock.class);
//Execute tasks with Synchronized
//runableTasks(TaskWithSync.class);
}
}
First time, executing tasks with Synchronized by calling method runableTasks(TaskWithSync.class);
<-- Start executing TaskWithSync Task -->
Thread Name: pool-1-thread-1, elaspsed time: 28 s
Thread Name: pool-1-thread-3, elaspsed time: 30 s
Thread Name: pool-1-thread-2, elaspsed time: 32 s
<-- TaskWithSync Tasks is complet -->
Second time, executing tasks with Lock by calling method runableTasks(TaskWithLock.class);
<-- Start executing TaskWithLock Task -->
Thread Name: pool-1-thread-3, elaspsed time: 23 s
Thread Name: pool-1-thread-2, elaspsed time: 23 s
Thread Name: pool-1-thread-1, elaspsed time: 23 s
<-- TaskWithLock Tasks is complet -->
With the above example using Lock
and synchronized
to run the tasks, I have some questions here:
Q1: The timestamp in the synchronized example, it reflects the mutex between 3 Threads. But why is the elapsed time in Lock example the same? I don't know why.
Q2: What's the difference between synchronized
and Lock
in my example?
Please help me out with these 2 questions.
Upvotes: 2
Views: 6626
Reputation: 11
synchronized ("A")
it's not a proper usage of synchronized block. you create a different String object (in some cases) when entering this sync block, so each your thread have a different lock object and do not synchronize. Proper usage may be like
synchronized(this)
or
public class TaskWithSync extends Task implements Runnable {
private Object lock = new Object();
@Override
public void run() {
synchronized (lock) {
doSomething();
}
}
}
In addition, you should use a single Runnable implemenation in different threads, or make your lock a static field
Upvotes: 1
Reputation: 2322
First of all, your example using synchronized
is ill conceived: it is a very bad idea to synchronize on object "A". Use the following idiom instead:
private final Object lock = new Object();
public void run() {
synchronized (lock) {
doSomething();
}
}
This is better because by hiding your lock from external objects, you are encapsulating your synchronization protocol and thereby implementing a safer synchronization policy.
Now, the difference between synchronized
and java.util.concurrent.locks.Lock
, is that the former is a synchronization primitive whereas the latter a higher level locking construct which provides more elaborate operations than synchornized
.
Fore more information you may look at http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Lock.html and http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantLock.html in particular.
Upvotes: 2